/* ====================================================================
 * The UncleGED Open Source Software License
 *
 * Copyright (c) 1999-2003 D. M. DeBacker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. Products derived from this software may not be called "UncleGED",
 *    nor may "UncleGED" appear in their name, without prior written
 *    permission of D. M. DeBacker.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL D. M. DEBACKER BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 */

using System;
using System.Collections;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace UGed
{
	class GedReader 
	{

		#region *** Declarations For The GedReader Class ***

		private bool _didCancel;
		private string  _sFile;
		//		private bool _bIsNotFirst;
		private bool _bStart;

		private StringFuncs sf = new StringFuncs();

		private Individuals MyIndividuals;
		private Children MyChildren;
		private Families MyFamilies;
		private Sources MySources;
		private Notes MyNotes;
		private Surnames MySurnames;
		private Gendices MyGendices;
		private FileInfo MyFileInfo;
		private TimeLineEntries MyTimeLineEntries;
		private Locations MyLocations;
		private Occupations MyOccupations;
		private GedcomLines myGedcomFile;
		private IndiLines myIndiLines;
		
		private UgedApplicationSettings configSettings;
		private LocalApplication localSettings;

		private const short GET_DRIVE = 0;
		private const short GET_DIRECTORY = 1;
		private const short GET_FILENAME = 2;
		private const short GET_EXTENSION = 3;


		private const string  Privacy = "[private]";

		private enum RecordTypes
		{
			rtHEAD = 0,
			rtINDI,
			rtFAM,
			rtNOTE,
			rtSOUR,
			rtOBJE,
			rtREPO,
			rtSUBN,
			rtSUBM,
		};

		#endregion

		/// <summary>
		/// Class constructor
		/// </summary>
		/// <param name=ConfigSettings></param>
		/// <param name=LocalSettings></param>
		/// <param name=FileName></param>
		/// 		
		public GedReader(UgedApplicationSettings ConfigSettings, LocalApplication LocalSettings, string FileName) 
		{
			localSettings = LocalSettings;
			configSettings = ConfigSettings;
			_sFile = FileName;
		}


		/// <summary>
		/// called by main to read and process the gedcom file
		/// </summary>
		/// <param name=sTheFile></param>
		/// <param name=bFullProcess></param>
		/// 		
		public bool ProcessGedComFile(string  sTheFile, bool bFullProcess) 
		{
			string  sFile;
			long NumBytes;
			int BytesRead = 0;

			_didCancel = false;

			MyIndividuals = new Individuals();
			MyChildren = new Children();
			MyFamilies = new Families();
			MySources = new Sources();
			MyNotes = new Notes();
			MySurnames = new Surnames();
			MyFileInfo = new FileInfo();
			MyTimeLineEntries = new TimeLineEntries();
			MyLocations = new Locations();
			MyOccupations = new Occupations();
			myGedcomFile = new GedcomLines();
			myIndiLines = new IndiLines();


			sFile = sTheFile;
			_sFile = GetFilePart(sTheFile, GET_FILENAME) + GetFilePart(sTheFile, GET_EXTENSION);


			configSettings.FileSource = _sFile;

			Tools.Logit("Reading " + sFile + "...");
			FileStream fs;
			StreamReader sr;
			try 
			{
				fs = new FileStream(sFile, FileMode.Open, FileAccess.Read);
				sr = new StreamReader(fs);
				NumBytes = fs.Length;
				Tools.Logit("The file size is: " + NumBytes.ToString() + " bytes");
			} 
			catch (Exception ex) 
			{
				Tools.Logit("Error in ProcessGedComFile : "  + ex.Message);
				return false;
			}

			//read a line from the gedcom file
			string a;
			while ((a = sr.ReadLine()) != null)
			{
				if ( _didCancel ) 
				{ 
					goto CLEAN_UP;
				}
				if ( a.Trim().Length  != 0 ) 
				{
					ProcessGedData(a);  //process each line
				}
				BytesRead = BytesRead + a.Length;
			}

			sr.Close();

			if ( bFullProcess == true ) 
			{
				Tools.Logit("Marking missing spouses...");
				FixFamiliesEach(); //if the husband or wife is an empty string change this to a question mark;
			}

			Tools.Logit("File process complete");

			if ( _didCancel ) 
			{ 
				goto CLEAN_UP;
			}
			if ( configSettings.Privacy ) 
			{
				MarkAsPrivate();
			}
			
			if ( _didCancel ) 
			{ 
				goto CLEAN_UP;
			}

			_bStart = true;
			_didCancel = false;

			return true;

			CLEAN_UP:
				
			_sFile = "";
			_didCancel = false;
			MyIndividuals = null;
			MyChildren = null;
			MyFamilies = null;
			MySources = null;
			MyNotes = null;
			MySurnames = null;
			_bStart = true;

			return true;
		}

					
		#region Process Ged Data
		//locals used by ProcessGedData
		private LifeEvent.EventTypes EventType;
		private RecordTypes RecType;
		private string  _xrefid;
		private string  _prevtag;
		private string  _prevsrcid;
		private string  _tag2;
		private string  _tag1;
		private int _currevent;
		private string  _filesrc;
		private string  _taglevel1;
		private bool _isevent;

		/// <summary>
		/// Called by ProcessGedComFile
		/// </summary>
		/// <param name=sGedLine></param>
		/// 		
		private void ProcessGedData(string sGedLine) 
		{
			
			if (sGedLine.Trim().Length == 0) return;

			int iLevel;
			string sTag;
			string sData;
			string sTempData;
			int iSpaceOne;
			int posDelim;
			int iLineNumber;
			
			Individual TheIndividual;
			Child TheChild;
			Family TheFamily;
			Source TheSource;
			Note TheNote;
			LifeEvent NewEvent;
			DateTime dtTempDate;

			const string SLASH = "/";

			if ( _bStart ) 
			{
				EventType = LifeEvent.EventTypes.etUnknown;
				RecType = RecordTypes.rtHEAD;
				_xrefid = "";
				_prevtag = "";
				_bStart = false;
			}

			iLineNumber = myGedcomFile.Add(sGedLine);

			iLevel = System.Convert.ToInt32(sf.Left(sGedLine, 1));
			iSpaceOne = sf.InStr(3, sGedLine, " ");
			if ( iSpaceOne != 0 ) 
			{
				sTag = sf.Trim(sf.Mid(sGedLine, 3, iSpaceOne - 2));
				sData = sf.Right(sGedLine, sf.Len(sGedLine) - iSpaceOne);
				sData = sf.Trim(sData);
			} 
			else if ( sf.Trim(sGedLine) != "" ) 
			{
				sTag = sf.Trim(sf.Right(sGedLine, sf.Len(sGedLine) - 2));
				sData = "";
			} 
			else 
			{
				sTag = "";
				sData = "";
			}

			if ( iLevel == 2 ) 
			{
				_tag2 = sTag;
			} 
			else if ( iLevel < 2 ) 
			{
				_tag2 = "";
			}

			if ( iLevel == 1 ) 
			{
				_tag1 = sTag;
			}	 
			else if ( iLevel < 1 ) 
			{
				_tag1 = "";
			}

			if ( iLevel == 0 ) 
			{
				_xrefid = sTag;
				sTag = sData;
				sData = "";
				_isevent = false;
				switch (sTag) 
				{
					case "HEAD":
						RecType = RecordTypes.rtHEAD;
						break;
					case "INDI":
						TheIndividual = new Individual();
						TheIndividual.ID = _xrefid;
						TheIndividual.LineNumber = iLineNumber;
						myIndiLines.Add(_xrefid, iLineNumber);
						MyIndividuals.Add(TheIndividual);
						RecType = RecordTypes.rtINDI;
						_currevent = 0;
						break;
					case "FAM":
						TheFamily = new Family();
						TheFamily.ID = _xrefid;
						MyFamilies.Add(TheFamily);
						RecType = RecordTypes.rtFAM;
						_currevent = 0;
						break;
					case "NOTE":
						TheNote = new Note();
						TheNote.ID = _xrefid;
						MyNotes.Add(TheNote);
						RecType = RecordTypes.rtNOTE;
						_currevent = 0;
						break;
					case "SOUR":
						TheSource = new Source();
						TheSource.ID = _xrefid;
						MySources.Add(TheSource);
						RecType = RecordTypes.rtSOUR;
						_currevent = 0;
						break;
					case "OBJE":
						//not used
						RecType = RecordTypes.rtOBJE;
						_currevent = 0;
						break;
					case "REPO":
						//not used
						RecType = RecordTypes.rtREPO;
						_currevent = 0;
						break;
					case "SUBN": //???????
						//not used
						RecType = RecordTypes.rtSUBN;
						_currevent = 0;
						break;
					case "SUBM":
						RecType = RecordTypes.rtSUBM;
						_currevent = 0;
						break;
				}
			} 
			else 
			{
				if ( iLevel == 1 ) 
				{
					_taglevel1 = sTag;
					_isevent = false;
				}
				switch (sTag) 
				{
					case "_DETS":
						EventType = LifeEvent.EventTypes.etDeathOfSpouse;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Death of Spouse";
						MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "_MILT":
						EventType = LifeEvent.EventTypes.etMilitary;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Military Service";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "_UNKN":
						EventType = LifeEvent.EventTypes.etUnknown;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "";
						NewEvent.EventDescription = sData;
					switch (RecType) 
					{
						case RecordTypes.rtINDI : 
							MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
							_isevent = true;
							break;
						case RecordTypes.rtFAM : 
							MyFamilies[_xrefid].LifeEvents.Add(NewEvent); 
							_isevent = true;
							break;
					}
						break;
					case "_UID":
						if(RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].PafUniqueID = sData;
						break;
					case "ADDR":
						if ( iLevel == 1 ) 
						{
							if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].Address = sData;
						}
						break;
					case "ADOP":
						//adoption in child record
						//need special handling for this
						break;
					case "ALIA":
						MyIndividuals[_xrefid].AliasName = sData;
						break;
					case "_AKA": //PAF uses this. why not use ALIA?;
						MyIndividuals[_xrefid].AliasName = sData;
						break;
					case "AUTH":
						if ( RecType == RecordTypes.rtSOUR ) 
						{
							MySources[_xrefid].Author = sData;
						}
						break;
					case "BIRT":
						EventType = LifeEvent.EventTypes.etBirth;
						
						//added in 0.7 (not in vb version)
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Birth";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BURI":
						//EventType = etBurial
						EventType = LifeEvent.EventTypes.etBurial;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Burial";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CALN":
						//the source call record
						//I don't use this
						break;
					case "CHIL": //inside a family record;
						TheChild = new Child();
						TheChild.ChildID = sData;
						TheChild.FamilyID = _xrefid;
						MyChildren.Add(TheChild);
						if ( MyFamilies[_xrefid].HasChildren == false ) 
						{
							MyFamilies[_xrefid].HasChildren = true;
						}
						break;
					case "CHAN":
						EventType = LifeEvent.EventTypes.etChange;
						break;
					case "CONC": //concatenation of a note;
						if ( RecType == RecordTypes.rtNOTE ) 
						{
							try
							{
								sTempData = MyNotes[_xrefid].NoteText;
								MyNotes[_xrefid].NoteText = sTempData + sData;
							} 
							catch {
								//this is necessary because FTW incorrectly places source notes at level 0
							}
						}
						if ( RecType == RecordTypes.rtINDI ) 
						{ //added for handling gedcoms from PAF
							if ((_tag2 == "SOUR" || _tag1 == "SOUR") && _prevtag != "TEXT" ) 
							{
								sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Note;
								MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sTempData + sData;
							} 
							else if ( _prevtag == "TEXT" ) 
							{
								sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText;
								MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sTempData + sData;
							} 
							else 
							{
//								sTempData = MyNotes[_xrefid].NoteText;
//								MyNotes[_xrefid].NoteText = sTempData + sData;
								sTempData = MyIndividuals[_xrefid].Notes;
								MyIndividuals[_xrefid].Notes = sTempData + sData;
							}
						}
						if ( RecType == RecordTypes.rtSOUR ) 
						{
							switch (_prevtag) 
							{
								case "TITL":
									sTempData = MySources[_xrefid].Title;
									MySources[_xrefid].Title = sTempData + sData;
									break;
								case "PUBL":
									sTempData = MySources[_xrefid].PublicationInfo;
									MySources[_xrefid].PublicationInfo = sTempData + sData;
									break;
							}
						}
						break;
					case "CONT":
						//continuation of a previous piece of data
						//could be an address or even a note
					switch (_prevtag) 
					{
						case "ADDR":
							if ( RecType == RecordTypes.rtINDI ) 
							{
								sTempData = MyIndividuals[_xrefid].Address;
								MyIndividuals[_xrefid].Address = sTempData + "<br>" + sData;
							}
							break;
						case "NOTE":
							if ( RecType == RecordTypes.rtNOTE ) 
							{
								sTempData = MyNotes[_xrefid].NoteText;
								MyNotes[_xrefid].NoteText = sTempData + "<br>" + sData;
							}
							if ( RecType == RecordTypes.rtINDI ) 
							{
								if ( _tag2 == "SOUR" || _tag1 == "SOUR" ) 
								{
									sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Note;
									MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sTempData + sData;
								} 
								else if ( _isevent == true ) 
								{
									sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote;
									MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote = sTempData + " " + sData;
								} 
								else 
								{
									TheNote = new Note(); 
									TheNote.ID = _xrefid;
									//this should fail if the the note has already been added to the collection
									MyNotes.Add(TheNote); 

									sTempData = MyNotes[_xrefid].NoteText;
									MyNotes[_xrefid].NoteText = sTempData + "<br>" + sData;
								}
							}
							if ( RecType == RecordTypes.rtSOUR ) 
							{ //added in 3.01
								sTempData = MySources[_xrefid].Note;
								MySources[_xrefid].Note = sTempData + "<br>" + sData;
							}
							break;
						case "AUTH": //author of source;
							if ( RecType == RecordTypes.rtSOUR ) 
							{
								sTempData = MySources[_xrefid].Author;
								MySources[_xrefid].Author = sTempData + "<br>" + sData;
							}
							break;
						case "TITL"://title of source;
							if ( RecType == RecordTypes.rtSOUR ) 
							{
								sTempData = MySources[_xrefid].Title;
								MySources[_xrefid].Title = sTempData + "<br>" + sData;
							}
							break;
						case "TEXT"://text from source;
							if ( RecType == RecordTypes.rtSOUR ) 
							{
								sTempData = MySources[_xrefid].SourceText;
								MySources[_xrefid].SourceText = sTempData + "<br>" + sData;
							} 
							else if ( RecType == RecordTypes.rtINDI ) 
							{
								sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText;
								MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sTempData + sData;
							}
							break;
						case "PAGE"://used by tmg for citations;
							if ( RecType == RecordTypes.rtINDI ) 
							{
								sTempData = MyIndividuals[_xrefid].Sources[_prevsrcid].Page;
								MyIndividuals[_xrefid].Sources[_prevsrcid].Page = sTempData + " " + sData;
							}
							break;
						default:
							break;
							//there are others but we will deal with them later
					}
						break;
					case "DATA":
						//when a source appears in a individual record
						//and text is associeted with the source note
						//need special handling for this
						break;
					case "DATE":
						if ( RecType != RecordTypes.rtHEAD ) 
						{
							if ( sf.IsDate(sData) ) 
							{
								sData = sf.DateValue(sData).ToString("MMMM dd, yyyy");
							} 
							else 
							{
								//added in 2.5
								sData = FixDate(sData);
							}
							switch (EventType) 
							{ 
								case LifeEvent.EventTypes.etUnknown:
								switch ( RecType) 
								{
									case RecordTypes.rtINDI:
										MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
										break;
									case RecordTypes.rtFAM:
										MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
										break;
								}
									break;
								case LifeEvent.EventTypes.etDeathOfSpouse:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBirth:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].BirthDateText = sData;
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etDeath:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].DeathDateText = sData;
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBurial:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etOccupation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData; 
									break;
								case LifeEvent.EventTypes.etMarriage:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].MarriageDateText = sData;
									break;
								case LifeEvent.EventTypes.etResidence:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etDivorce:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etImmigration:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etMilitary:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etOther:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etElected:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etExcommunicated:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etMission:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBaptismLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBaptism:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBar_Mitzvah:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBat_Mitzvah:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etBlessing:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etCaste:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etCensus:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etChristening:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etConfirmation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etConfirmationLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etCremation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etEducation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etEmigration:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etEndowmentLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etFirstCommunion:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etGraduation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etNaturalization:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etOrdination:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etProbate:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etProperty:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etReligion:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etRetirement:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etSealedToParentsLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etSSN:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etWill:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventDateString = sData;
									break;
								case LifeEvent.EventTypes.etChange:
									if ( RecType == RecordTypes.rtINDI ) 
									{
										dtTempDate = sf.DateValue(sData);
										if ( dtTempDate > MyIndividuals[_xrefid].LastChangeDate ) 
										{
											MyIndividuals[_xrefid].LastChangeDate = dtTempDate;
										}
									}
									if ( RecType == RecordTypes.rtFAM ) 
									{
										dtTempDate = sf.DateValue(sData);
										if ( dtTempDate > MyFamilies[_xrefid].LastChangeDate ) 
										{
											MyFamilies[_xrefid].LastChangeDate = dtTempDate;
										}
									}
									break;
							}
						} 
						else 
						{
							MyFileInfo.CreationDate = sData;
						}
						break;
					case "DEAT":
						EventType = LifeEvent.EventTypes.etDeath;

						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Death";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "DIV": //occurs inside a family record;
						EventType = LifeEvent.EventTypes.etDivorce;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Divorced";
						if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
						if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "EMAIL":
						if ( RecType == RecordTypes.rtSUBM ) 
						{
							MyFileInfo.SubmitterEmail = sData;
						}
						break;
					case "EVEN":
						//this is a special event defined by type
						//there could be many of these and this version
						//currently handles only one
						if ( RecType == RecordTypes.rtINDI ) 
						{
							EventType = LifeEvent.EventTypes.etOther;
							_currevent++;
							NewEvent = new LifeEvent();
							NewEvent.ID = _xrefid + _currevent.ToString();
							NewEvent.EventType = EventType;
							NewEvent.EventText = sData;
							MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
							_isevent = true;
						}
						break;
					case "FAMC":
						MyIndividuals[_xrefid].FamilyID = sData;//added in ver 1.2;
						TheChild = new Child();
						TheChild.ChildID = _xrefid;
						TheChild.FamilyID = sData;
						MyChildren.Add(TheChild);
						break;
					case "FAMS":
						//individual is a spouse in a particular family
						//attempt to create a new family
						TheFamily = new Family();
						TheFamily.ID = sData;
						MyFamilies.Add(TheFamily);
						MyIndividuals[_xrefid].HasOwnFamily = true;
						MyIndividuals[_xrefid].FamList.Add(sData, sData);
					switch (MyIndividuals[_xrefid].Sex) 
					{
						case "M":
							MyFamilies[sData].Husband = _xrefid;
							break;
						case "F":
							MyFamilies[sData].Wife = _xrefid;
							break;
					}
						break;
					case "FILE":
						if ( RecType == RecordTypes.rtHEAD ) 
						{
							MyFileInfo.SourceFile = sData;
						}
						break;
					case "HUSB":
						MyFamilies[_xrefid].Husband = sData;
						break;
					case "IMMI":
						EventType = LifeEvent.EventTypes.etImmigration;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Immigrated";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "MARR":
						EventType = LifeEvent.EventTypes.etMarriage;
						break;
					case "MEDI":
						//media of the source
						if ( RecType == RecordTypes.rtSOUR ) 
						{
							MySources[_xrefid].Media = sData;
						}
						break;
					case "NAME":
						if ( RecType == RecordTypes.rtHEAD ) 
						{
							MyFileInfo.SourceName = sData;
						}
						if ( RecType == RecordTypes.rtSUBM ) 
						{
							MyFileInfo.SubmitterName = sData;
						}
						if ( iLevel == 1 ) 
						{
							if ( RecType == RecordTypes.rtINDI ) 
							{
								MyIndividuals[_xrefid].Surname = sData; //in case it is just a single name (ex. <Living>)

								//extract the surname and the forenames
								posDelim = sf.InStr(sData, SLASH);
								if ( posDelim != 0 ) 
								{
									MyIndividuals[_xrefid].Forenames = sf.Trim(sf.Left(sData, posDelim - 1));
									MyIndividuals[_xrefid].Surname = sf.Trim(sf.Right(sData, sf.Len(sData) - posDelim));
								}
								posDelim = sf.InStr(MyIndividuals[_xrefid].Surname, SLASH);
								if ( posDelim != 0 ) 
								{
									sTempData = MyIndividuals[_xrefid].Surname;
									MyIndividuals[_xrefid].Surname = sf.Trim(sf.Left(MyIndividuals[_xrefid].Surname, posDelim - 1));
								}

								//look for a comma
								posDelim = sf.InStr(MyIndividuals[_xrefid].Forenames, ",");
								if ( posDelim != 0 ) 
								{
									MyIndividuals[_xrefid].Suffix = sf.Trim(sf.Right(MyIndividuals[_xrefid].Forenames, sf.Len(MyIndividuals[_xrefid].Forenames) - posDelim));
									MyIndividuals[_xrefid].Forenames = sf.Trim(sf.Left(MyIndividuals[_xrefid].Forenames, posDelim - 1));
								}

								if ( configSettings.SurnamesAllCaps && MyIndividuals[_xrefid].Surname != "" ) 
								{
									MyIndividuals[_xrefid].Surname = sf.UCase(MyIndividuals[_xrefid].Surname);
								}
							}
						}
						break;
					case "NATI":
						EventType = LifeEvent.EventTypes.etNationality;
						break;
					case "NOTE":
						if ( RecType == RecordTypes.rtINDI ) 
						{
							if ( _tag2 == "SOUR" || _tag1 == "SOUR" ) 
							{
								MyIndividuals[_xrefid].Sources[_prevsrcid].Note = sData;
							} 
							else 
							{
								switch (_filesrc) 
								{
									case "PAF":
										TheNote = new Note(); //trying to fix problem btwn the way that PAF and FTW do notes;
										TheNote.ID = _xrefid;
										MyNotes.Add(TheNote); //this should fail if the the note has already been added to the collection;
										MyNotes[_xrefid].NoteText = sData;
										MyIndividuals[_xrefid].Notes = _xrefid;
										break;
									case "FTW":
										MyIndividuals[_xrefid].Notes = sData;
										break;
									case "LEG":
										goto case "TMG";
									case "TMG":
										if (_isevent == true) 
										{
											MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventNote = sData;
										} 
										else 
										{
											MyIndividuals[_xrefid].Notes = sData;
										}
										break;
								}
							}
						} 
						else if ( RecType == RecordTypes.rtFAM ) 
						{ //added ver. 2.07 to handle marriage notes
							switch (_filesrc) 
							{
								case "PAF":
									TheNote = new Note(); //trying to fix problem btwn the way that PAF and FTW do notes;
									TheNote.ID = _xrefid;
									MyNotes.Add(TheNote);//this should fail if the the note has already been added to the collection;
									MyNotes[_xrefid].NoteText = sData;
									MyFamilies[_xrefid].Notes = _xrefid;
									break;
								case "FTW":
									MyFamilies[_xrefid].Notes = sData;
									break;
								case "LEG":
									MyFamilies[_xrefid].Notes = sData;
									break;
							}
						} 
						else if ( RecType == RecordTypes.rtSOUR ) 
						{ //added in 3.01
							MySources[_xrefid].Note = sData;
						} 
						else if ( RecType == RecordTypes.rtNOTE ) 
						{
							MyNotes[_xrefid].NoteText = sData;		
						}
						break;
					case "OCCU":
						EventType = LifeEvent.EventTypes.etOccupation;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Occupation: " + sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "PAGE":
						//used in source not used here
						//started using in 3.01
						if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].Sources[_prevsrcid].Page = sData;
						break;
					case "ABBR":
						//used in source not used here
						//started using in 5.01
						if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].Sources[_prevsrcid].Abbreviation = sData;
						break;
					case "PUBL":
						if ( RecType == RecordTypes.rtSOUR ) 
						{
							MySources[_xrefid].PublicationInfo = sData;
						}
						break;
					case "PLAC":
						if ( RecType != RecordTypes.rtHEAD ) 
						{
							switch ( EventType) 
							{
	
								case LifeEvent.EventTypes.etUnknown:
								switch (RecType) 
								{ 
									case RecordTypes.rtINDI:
										MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
										break;
									case RecordTypes.rtFAM:
										MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
										break;
								}
									break;
								case LifeEvent.EventTypes.etDeathOfSpouse:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBirth:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].BirthPlace = sData;
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etDeath:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].DeathPlace = sData;
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBurial:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etOccupation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etMarriage:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].MarriagePlace = sData;
									break;
								case LifeEvent.EventTypes.etResidence:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etDivorce:
									if ( RecType == RecordTypes.rtFAM ) MyFamilies[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etNationality:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].Nationality = sData;
									break;
								case LifeEvent.EventTypes.etImmigration:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etMilitary:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etOther:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etElected:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etExcommunicated:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etMission:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBaptismLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBaptism:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBar_Mitzvah:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBat_Mitzvah:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etBlessing:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etCaste:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etCensus:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etChristening:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etConfirmation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etConfirmationLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etCremation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etEducation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etEmigration:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etEndowmentLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etFirstCommunion:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etGraduation:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etNaturalization:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etOrdination:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etProbate:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etProperty:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etReligion:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etRetirement:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etSealedToParentsLDS:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etSSN:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
								case LifeEvent.EventTypes.etWill:
									if ( RecType == RecordTypes.rtINDI ) MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventPlace = sData;
									break;
							}
						}
						break;
					case "REFN":
						if ( RecType == RecordTypes.rtINDI ) 
						{
							MyIndividuals[_xrefid].ReferenceNumber = sData;
						}
						if ( RecType == RecordTypes.rtFAM ) 
						{
							MyFamilies[_xrefid].ReferenceNumber = sData;
						}
						break;
					case "REPO":
						//used in sources
						break;
					case "RESI":
						EventType = LifeEvent.EventTypes.etResidence;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Residence";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "SEX":
						MyIndividuals[_xrefid].Sex = sData;
						break;
					case "SOUR":
						if ( RecType == RecordTypes.rtHEAD ) 
						{ //this is the source of the GEDCOM file
							_filesrc = sf.UCase(sf.Left(sData, 3));
							MyFileInfo.Source = sData;

						}
						if ( sf.Left(sData, 1) == "@" ) 
						{
							TheSource = new Source();
							TheSource.ID = sData;
							_prevsrcid = sData;
							TheSource.EventTag = _taglevel1;
							switch (RecType) 
							{
								case RecordTypes.rtINDI : MyIndividuals[_xrefid].Sources.Add(TheSource);
									break;
								case RecordTypes.rtFAM : MyFamilies[_xrefid].Sources.Add(TheSource);
									break;
							}
						}
						break;
					case "TEXT":
						if (RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].Sources[_prevsrcid].SourceText = sData;
						break;
					case "TIME":
						if ( RecType == RecordTypes.rtHEAD ) 
						{
							MyFileInfo.CreationTime = sData;
						}
						break;
					case "TITL":
						if ( RecType == RecordTypes.rtSOUR ) 
						{
							MySources[_xrefid].Title = sData;
						}
						break;
					case "TYPE":
						if ( _prevtag == "EVEN" && RecType == RecordTypes.rtINDI ) 
						{
							if ( sData == "Occupation" ) 
							{
								MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventType = LifeEvent.EventTypes.etOccupation;
								sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText;
								MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText = "Occupation: " + sTempData;
							} 
							else 
							{
								sTempData = MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText;
								MyIndividuals[_xrefid].LifeEvents[_xrefid + _currevent.ToString()].EventText = sData + "&nbsp;" + sTempData;
							}
						}
						break;
					case "VERS":
						//version of software that produced this
						if ( RecType == RecordTypes.rtHEAD && MyFileInfo.Version == "" ) 
						{
							MyFileInfo.Version = sData;
						}
						break;
					case "WIFE":
						MyFamilies[_xrefid].Wife = sData;
						break;
					case "_ELEC":
						EventType = LifeEvent.EventTypes.etElected;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Elected";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "_EXCM":
						EventType = LifeEvent.EventTypes.etExcommunicated;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Excommunicated";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "_MISN":
						EventType = LifeEvent.EventTypes.etMission;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Mission";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BAPL":
						EventType = LifeEvent.EventTypes.etBaptismLDS;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Baptism (LDS)";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BAPM":
						EventType = LifeEvent.EventTypes.etBaptism;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Baptism";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BARM":
						EventType = LifeEvent.EventTypes.etBar_Mitzvah;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Bar-Mitzvah";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BASM":
						EventType = LifeEvent.EventTypes.etBat_Mitzvah;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Bat-Mitzvah";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "BLES":
						EventType = LifeEvent.EventTypes.etBlessing;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Blessing";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CAST":
						EventType = LifeEvent.EventTypes.etCaste;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Caste";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CENS":
						EventType = LifeEvent.EventTypes.etCensus;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Census";
						NewEvent.EventDescription = sData;
						if(RecType == RecordTypes.rtINDI) MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						if(RecType == RecordTypes.rtFAM) MyFamilies[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CHR":
						EventType = LifeEvent.EventTypes.etChristening;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Christening";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CONF":
						EventType = LifeEvent.EventTypes.etConfirmation;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Confirmation";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CONL":
						EventType = LifeEvent.EventTypes.etConfirmationLDS;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Confirmation (LDS)";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "CREM":
						EventType = LifeEvent.EventTypes.etCremation;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Cremation";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "EDUC":
						EventType = LifeEvent.EventTypes.etEducation;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Education";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "EMIG":
						EventType = LifeEvent.EventTypes.etEmigration;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Emigration";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "ENDL":
						EventType = LifeEvent.EventTypes.etEndowmentLDS;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Endowment (LDS)";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "FCOM":
						EventType = LifeEvent.EventTypes.etFirstCommunion;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "First Communion";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "GRAD":
						EventType = LifeEvent.EventTypes.etGraduation;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Graduation";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "NATU":
						EventType = LifeEvent.EventTypes.etNaturalization;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Naturalization";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "ORDN":
						EventType = LifeEvent.EventTypes.etOrdination;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Ordination";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "PROB":
						EventType = LifeEvent.EventTypes.etProbate;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Probate";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "PROP":
						EventType = LifeEvent.EventTypes.etProperty;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Property";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "RELI":
						EventType = LifeEvent.EventTypes.etReligion;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Religion";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "RETI":
						EventType = LifeEvent.EventTypes.etRetirement;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Retirement";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "SLGC":
						EventType = LifeEvent.EventTypes.etSealedToParentsLDS;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Sealed to parents (LDS)";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "SSN":
						EventType = LifeEvent.EventTypes.etSSN;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "SSN";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
					case "WILL":
						EventType = LifeEvent.EventTypes.etWill;
						_currevent++;
						NewEvent = new LifeEvent();
						NewEvent.ID = _xrefid + _currevent.ToString();
						NewEvent.EventType = EventType;
						NewEvent.EventText = "Will";
						NewEvent.EventDescription = sData;
						MyIndividuals[_xrefid].LifeEvents.Add(NewEvent);
						_isevent = true;
						break;
				}
			}

			if ( sTag != "CONT" && sTag != "CONC" ) 
			{
				_prevtag = sTag;
			}

		}

		#endregion

		/// <summary>
		/// called by main to build the web pages
		/// </summary>
		/// 		
		public void SaveAsHTM() 
		{

			try 
			{

				if ( configSettings.CreateGendexFile == true ) 
				{
					MyGendices = new Gendices();
				}


				Tools.Logit("Writing HTML Pages...");

				_didCancel = false;

				string[] TestFiles = Directory.GetFiles(@configSettings.HtmlPath, "*.htm*");

				if ( TestFiles.Length != 0 ) 
				{
					Tools.Logit("The directory " + configSettings.HtmlPath + " contains HTML files. Some files may be overwritten.");
				}

				Tools.Logit("Building Family Pages..");
				if ( BuildFamilyPages() == false ) 
				{ 
					goto HTML_CLEAN_UP;
				}
				if ( _didCancel ) 
				{ 
					goto HTML_CLEAN_UP; 
				}
				Tools.Logit("Building Index Page...");
				BuildIndexEach();
				if ( _didCancel ) goto HTML_CLEAN_UP;
				Tools.Logit("Building Sources Page...");
				BuildBiblio();
				if ( _didCancel ) goto HTML_CLEAN_UP;
				Tools.Logit("Building Surname Page...");
				BuildSurnamePage();
				if ( _didCancel ) goto HTML_CLEAN_UP;
				if ( configSettings.CreateStatsPage == true ) 
				{
					Tools.Logit("Building Stats Page...");
					BuildStatisticsPage();
					if ( _didCancel ) goto HTML_CLEAN_UP;
				}
				BuildTableOfContents();
				if ( _didCancel ) goto HTML_CLEAN_UP;
				if ( configSettings.CreateGendexFile == true ) 
				{
					Tools.Logit("Building Gendex file...");
					BuildGendexFile();
					if ( _didCancel ) goto HTML_CLEAN_UP;
				}

				//added in 3.01
				if ( configSettings.CreateChronoPage == true ) 
				{
					Tools.Logit("Building Chronology Page...");
					BuildTimeLinePage();
					if ( _didCancel ) goto HTML_CLEAN_UP;
				}


				//added in 3.02
				if ( configSettings.CreateLocPage == true ) 
				{
					Tools.Logit("Building Locations Page...");
					BuildLocationsReport();
					if ( _didCancel ) goto HTML_CLEAN_UP;
				}

				//added in 3.03
				if ( configSettings.CreateOccupationsPage == true ) 
				{
					Tools.Logit("Building Occupations Page...");
					BuildOccupationsReport();
					if ( _didCancel ) goto HTML_CLEAN_UP;
				}

				_didCancel = false;
				Tools.Logit("HTML files have been created in " + configSettings.HtmlPath + ".");
				return;

			HTML_CLEAN_UP:
				_didCancel = false;

				return;
			}
			catch(Exception ex)
			{
				Tools.Logit("The following error occured in SaveAsHTML while processing the GEDCOM file:" + '\n' + "Error: " + ex.Message);
				Tools.Logit("Incomplete");
				_didCancel = false;
			}
		}

		
		#region Page Building methods

		/// <summary>
		/// Summary of BuildOccupationsReport.
		/// </summary>
		/// 		
		private void BuildOccupationsReport() 
		{
			string  sFile;
			int iOccCount;
			int iNumOcc;
			string  sCurrOcc;
			string  sPrevOcc;
			string  sOccupation;
			string  sFile2;

			GetOccupations();

			iNumOcc = MyOccupations.Count;

			SortedList  sl = new SortedList(iNumOcc);

			char QUOTE = '"';

			if ( iNumOcc == 0 )return;


			sl.Clear();

			for ( iOccCount = 0 ; iOccCount <= iNumOcc - 1; iOccCount++)
			{
				sl.Add(MyOccupations[iOccCount].OccupationTitle + CreateGUIDKey(), iOccCount);
			} // iOccCount

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\occupations.html";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_occupations.html";
			}

			FileStream  fs1 = new FileStream(sFile, FileMode.Create);
			StreamWriter  sw1 = new StreamWriter(fs1);

			sFile2 = Tools.GetPath() + "\\occ_report.txt";

			FileStream  fs2 = new FileStream(sFile2, FileMode.Create);
			StreamWriter  sw2 = new StreamWriter(fs2);

			//file header
			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>Occupations Report</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<h1><p align=" + QUOTE + "center" + QUOTE + ">Occupations</p></h1>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sPrevOcc = "#";
			for ( iOccCount = 0 ; iOccCount <= iNumOcc - 1; iOccCount++)
			{
				if ( _didCancel ) goto BUILDOCC_EXIT;
				//strip off GUID
				sOccupation = sf.Left((string)sl.GetKey(iOccCount), sf.Len((string)sl.GetKey(iOccCount)) - 36); 
				if ( sOccupation != "" ) 
				{
					sCurrOcc = sOccupation;
					if ( sPrevOcc != sCurrOcc ) 
					{
						sw1.WriteLine("</ul>");  //end prev list;
						sw1.Write("<H2>");
						sw1.Write(sCurrOcc);
						sw2.WriteLine(sCurrOcc);
						sw1.WriteLine("</H2>");
						sPrevOcc = sCurrOcc;
						sw1.WriteLine("<ul>");  //start a new list;
					}
					sw1.WriteLine("<li>" + MyOccupations[(int)sl.GetByIndex(iOccCount)].PersonName + "</li>");
				}
			} // iOccCount

			sw1.WriteLine("</ul>");  //end prev list;

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString() + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" ) 
				{
					sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
					sw1.Write(configSettings.AuthorsName);
					if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
					sw1.WriteLine("</CENTER></P></FONT>");
				}
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToShortDateString() + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00")); //);
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			BUILDOCC_EXIT:
				sw1.Close();
			fs1.Close();
			sw2.Close();
			fs2.Close();
		}


		/// <summary>
		/// Summary of GetOccupations.
		/// </summary>
		/// 		
		private void GetOccupations() 
		{
			//added in 3.03
			int iCnt;
			int jCnt;
			int iTotItems;
			string  sEventDetails;
			string  sOccupation;
			string  sName;
			int iNumEvents;

			char Q = '"';

			//wipe everything out
			MyOccupations = new Occupations();

			//life events
			iTotItems = MyIndividuals.Count;
      
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
					if ( iNumEvents != 0 ) 
					{
						for ( jCnt = 0 ; jCnt <= iNumEvents - 1; jCnt++)
						{
							sEventDetails = "";
							if ( MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etOccupation ) 
							{
								if ( configSettings.OccLocEqualsOccText == true ) 
								{
									sOccupation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace);
								} 
								else 
								{
									sOccupation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventText);
								}

								if ( sf.Trim(sOccupation) == "" ) break;

								sOccupation = FixOccupation(sOccupation);

								sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
								if ( MyIndividuals[iCnt].Suffix != "" ) 
								{
									sName = sName + ", " + MyIndividuals[iCnt].Suffix;
								}

								if ( configSettings.ChronoLinks == true ) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
								sEventDetails = sEventDetails + sName;
								if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";

								MyOccupations.Add(sOccupation, sEventDetails, CreateGUIDKey());
							}
						} // jCnt				
					} // iCnt
				}
			}
		}


		/// <summary>
		/// Summary of BuildFamilyPages.
		/// </summary>
		/// 		
		private bool BuildFamilyPages() 
		{
			string  sFile;
			int iFamCount;
			int iChildCount;
			int iNumFams;
			string  FamRefID;
			string  sTitle;
			string  sHusband;
			string  sWife;
			string  sChTitle;
			string  sChHusband;
			string  sChWife;
			string  sLink;
			ArrayList sLinks  = new ArrayList();
			ArrayList sLnkFamID  = new ArrayList();
			string  sFather;
			string  sMother;
			int iNumLinks;
			int iLinkcount;
			string  sParents;
			bool bHasKids;
			int iNumEvents;
			int iNumSrcs;
//			Surname NewSurname;
			string  sSrnLink;
			bool bDoNotes;
			string  sFamKey;
			bool bNotesOkay;
			string  sListFile;
			string  sChildName;
			bool bDidLine = false;
			string  sGenUrl;
			DateTime dtLastChangeDate;
			//ver 4
			int NumOtherMarriages;
			ArrayList aryOtherFams; 
			int iOtherCnt;

			FileStream fs1 = null;
			StreamWriter sw1  = null;
			FileStream fs2  = null;
			StreamWriter sw2  = null;

		
			try
			{
				iNumFams = MyFamilies.Count;

				char QUOTE = '"';

				if ( configSettings.CreateListReport == true ) 
				{
					sListFile = Tools.GetPath() + "\\list.txt";

					fs2 = new FileStream(sListFile, FileMode.Create);
					sw2 = new StreamWriter(fs2);
				} 
		
				if ( iNumFams == 0 ) return true;
				for ( iFamCount = 0 ; iFamCount <= iNumFams - 1; iFamCount++)
				{

					if ( _didCancel ) goto BUILDFAMILY_EXIT;
					bHasKids = false;
					//get the fam id
					FamRefID = MyFamilies[iFamCount].ID;

					dtLastChangeDate = MyFamilies[iFamCount].LastChangeDate; //start the last changed date;

					//establish the file name
					sFile = sf.Right(FamRefID, sf.Len(FamRefID) - 2);
					sFile = sf.Left(sFile, sf.Len(sFile) - 1);
					int iFileNumber = System.Convert.ToInt32(sFile); //added on v.6;
					sFile = iFileNumber.ToString("000");
					if ( localSettings.FirstFamily == 0 ) 
					{
						localSettings.FirstFamily = System.Convert.ToInt32(sFile);
					}
					if ( System.Convert.ToInt32(sFile) < localSettings.FirstFamily ) 
					{
						localSettings.FirstFamily = System.Convert.ToInt32(sFile);
					}
					sSrnLink = configSettings.FamFilePrefix + sFile + ".html";
					sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + sFile + ".html";
					Tools.Logit("Building Family Page " + LongDirFix(sFile, 32) + "...");

					//the husband
					if ( MyFamilies[iFamCount].Husband != "?" ) 
					{
						sHusband = MyIndividuals[MyFamilies[iFamCount].Husband].Forenames + " " + MyIndividuals[MyFamilies[iFamCount].Husband].Surname;
						if ( MyIndividuals[MyFamilies[iFamCount].Husband].Suffix != "" ) 
						{
							sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iFamCount].Husband].Suffix;
						}

						//modified in ver 2.05 for counting surnames
						//THIS IS ALL WRONG - THIS IS ONLY COUNTING HUSBAND AND WIFE - NOT INDIVIDUALS
//						NewSurname = new Surname();
//						NewSurname.FamilyName = sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname);
//						NewSurname.FirstLink = sSrnLink;
//						if ( MySurnames.Add(NewSurname) == false ) 
//						{
//							//if it failed to add then increment it
//							MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
//						}
//						NewSurname = null;

						if ( MyIndividuals[MyFamilies[iFamCount].Husband].LastChangeDate > dtLastChangeDate ) dtLastChangeDate = MyIndividuals[MyFamilies[iFamCount].Husband].LastChangeDate;

					} 
					else 
					{
						sHusband = "?";
					}

					//the wife
					if ( MyFamilies[iFamCount].Wife != "?" ) 
					{
						sWife = MyIndividuals[MyFamilies[iFamCount].Wife].Forenames + " " + MyIndividuals[MyFamilies[iFamCount].Wife].Surname;
						if ( MyIndividuals[MyFamilies[iFamCount].Wife].Suffix != "" ) 
						{
							sWife = sWife + ", " + MyIndividuals[MyFamilies[iFamCount].Wife].Suffix;
						}

//						NewSurname = new Surname();
//						NewSurname.FamilyName = sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname);
//						NewSurname.FirstLink = sSrnLink;
//						if ( MySurnames.Add(NewSurname) == false ) 
//						{
//							//if it failed to add then increment it
//							MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
//						}
//						NewSurname = null;

						if ( MyIndividuals[MyFamilies[iFamCount].Wife].LastChangeDate > dtLastChangeDate ) dtLastChangeDate = MyIndividuals[MyFamilies[iFamCount].Wife].LastChangeDate;
					} 
					else 
					{
						sWife = "?";
					}

					//title of web page
					sTitle = sHusband + "\\" + sWife;

					if ( configSettings.DisplayMRIN == true ) 
					{
						sTitle = sTitle + " (MRIN:" + FixRin(MyFamilies[iFamCount].ID) + ")";
					}

					//open the file
					fs1 = new FileStream(sFile, FileMode.Create);
					sw1 = new StreamWriter(fs1);

					//file header
					sw1.WriteLine("<HTML>");
					sw1.WriteLine("<HEAD>");
					if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
					sw1.WriteLine("<TITLE>" + sTitle + "</TITLE>");
					sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
					sw1.WriteLine("</HEAD>");
					if ( configSettings.UseBackground ) 
					{
						sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
					} 
					else 
					{
						sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
					}
					if ( configSettings.UseBanner ) 
					{
						sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
					}

					//husband details
					if ( sHusband != "?" ) 
					{
						sw1.Write("<B>" + sHusband + "</B>");

						if ( configSettings.DisplayRIN == true ) 
						{
							sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[MyFamilies[iFamCount].Husband].ID) + ")");
						}

						if ( configSettings.CreateListReport == true ) 
						{
							sw2.WriteLine("{0},{1},{2}", sHusband, MyIndividuals[MyFamilies[iFamCount].Husband].ReferenceNumber, sSrnLink);
						}

						if ( configSettings.CreateGendexFile == true ) 
						{
							//"GENDEX.txt"
							sGenUrl = sSrnLink;
							MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname), MyIndividuals[MyFamilies[iFamCount].Husband].Forenames + " /" + sf.UCase(MyIndividuals[MyFamilies[iFamCount].Husband].Surname) + "/", (MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText), (MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace), (MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText), (MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace), CreateGUIDKey());
						}


						//find his parents
						sFamKey = MyIndividuals[MyFamilies[iFamCount].Husband].FamilyID + MyIndividuals[MyFamilies[iFamCount].Husband].ID;
            
					{
						Child child;
						try
						{ 
							child = MyChildren[sFamKey];
						} 
						catch 
						{
							child = null;
						}
						if ( child != null ) 
						{
							//he is in this family
							sLink = "";
							sParents = "";
							sw1.Write(", son of ");
							sLink = MyFamilies[child.FamilyID].ID;
							sLink = sf.Right(sLink, sf.Len(sLink) - 2);
							int iLinkNumber = System.Convert.ToInt32(sf.Left(sLink, sf.Len(sLink) - 1));
							sLink = iLinkNumber.ToString("000");
							sLink = configSettings.FamFilePrefix + sLink + ".html";
							if ( sLink != "" )  sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">");
							if ( MyFamilies[child.FamilyID].Husband != "?" ) 
							{
								sFather = MyIndividuals[MyFamilies[child.FamilyID].Husband].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Husband].Surname;
								sParents = sFather;
								if ( MyFamilies[child.FamilyID].Wife != "?" ) 
								{
									sParents = sFather + " and ";
								}
							}
							if ( MyFamilies[child.FamilyID].Wife != "?" ) 
							{
								sMother = MyIndividuals[MyFamilies[child.FamilyID].Wife].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Wife].Surname;
								sParents = sParents + sMother;
							}
							sw1.WriteLine(sParents);
							if ( sLink != "" ) sw1.WriteLine("</A>,");
						} 
						child = null;
					}

						if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != "" ) 
						{
							if ( sf.IsDate(MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText) ) 
							{
								sw1.Write(" was born  " + sf.DateValue(MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText).ToString("MMMM dd,yyyy"));
							} 
							else 
							{
								sw1.Write(" was born  " + MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText);
							}
						}
						if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace != "" ) 
						{
							sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Husband].BirthPlace)));
							sw1.Write(". ");
						} 
						else 
						{
							sw1.Write(". ");
						}
						if ( sWife != "?" ) 
						{
							sw1.WriteLine("He married " + sWife);

							if ( MyFamilies[iFamCount].MarriageDateText != "" ) 
							{
								sw1.Write(MyFamilies[iFamCount].MarriageDateText);
							}
							if ( MyFamilies[iFamCount].MarriagePlace != "" ) 
							{
								sw1.Write(" in " + FixEstLoc((MyFamilies[iFamCount].MarriagePlace)));
								sw1.Write(". ");
							} 
							else 
							{
								sw1.Write(". ");
							}
						}
						if ( MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText != "" || MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace != "" ) 
						{
							sw1.Write("He died " + MyIndividuals[MyFamilies[iFamCount].Husband].DeathDateText);
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace != "" ) 
							{
								sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Husband].DeathPlace)));
							}
							sw1.Write(". ");
						}
					}

					//wife details
					if ( sWife != "?" ) 
					{
						sw1.Write("<B>" + sWife + "</B>");

						if ( configSettings.DisplayRIN == true ) 
						{
							sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[MyFamilies[iFamCount].Wife].ID) + ")");
						}

						if ( configSettings.CreateListReport == true ) 
						{
							sw2.WriteLine("{0},{1},{2}", sWife, MyIndividuals[MyFamilies[iFamCount].Wife].ReferenceNumber, sSrnLink);
						}

						if ( configSettings.CreateGendexFile == true ) 
						{
							//"GENDEX.txt"
							sGenUrl = sSrnLink;
							MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname), MyIndividuals[MyFamilies[iFamCount].Wife].Forenames + " /" + sf.UCase(MyIndividuals[MyFamilies[iFamCount].Wife].Surname) + "/", MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText, MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace, MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText, MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace, CreateGUIDKey());
						}

						//find her parents
						sFamKey = MyIndividuals[MyFamilies[iFamCount].Wife].FamilyID + MyIndividuals[MyFamilies[iFamCount].Wife].ID;

					{
						Child child;
						try
						{
							child = MyChildren[sFamKey]; 
						} 
						catch{child = null; }
						if ( child != null ) 
						{
							//she is in this family
							sLink = "";
							sParents = "";
							sw1.Write(", daughter of ");
							sLink = MyFamilies[child.FamilyID].ID;
							sLink = sf.Right(sLink, sf.Len(sLink) - 2);
							int iLinkNumber = System.Convert.ToInt32(sf.Left(sLink, sf.Len(sLink) - 1));
							sLink = iLinkNumber.ToString("000");
							sLink = configSettings.FamFilePrefix + sLink + ".html";
							if ( sLink != "" ) sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">");
							if ( MyFamilies[child.FamilyID].Husband != "?" ) 
							{
								sFather = MyIndividuals[MyFamilies[child.FamilyID].Husband].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Husband].Surname;
								sParents = sFather;
								if ( MyFamilies[child.FamilyID].Wife != "?" ) 
								{
									sParents = sParents + " and ";
								}
							}
							if ( MyFamilies[child.FamilyID].Wife != "?" ) 
							{
								sMother = MyIndividuals[MyFamilies[child.FamilyID].Wife].Forenames + " " + MyIndividuals[MyFamilies[child.FamilyID].Wife].Surname;
								sParents = sParents + sMother;
							}
							sw1.WriteLine(sParents);
							if ( sLink != "" ) sw1.WriteLine("</A>,");
						} 
						child = null;
					}

						if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != "" ) 
						{
							sw1.Write(" was born  " + MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText);
						}
						if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace != "" ) 
						{
							sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Wife].BirthPlace)));
						}
						sw1.Write(". ");
						if ( MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText != "" || MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace != "" ) 
						{
							sw1.Write("She died " + MyIndividuals[MyFamilies[iFamCount].Wife].DeathDateText);
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace != "" ) 
							{
								sw1.Write(" in " + FixEstLoc((MyIndividuals[MyFamilies[iFamCount].Wife].DeathPlace)));
							}
							sw1.WriteLine(". ");
						}
					}
					sw1.WriteLine("</P>");

					bHasKids = MyFamilies[iFamCount].HasChildren;

					if ( bHasKids ) 
					{
						iChildCount = 0;
						sw1.WriteLine("<br>");
						sw1.Write("Children of ");
						if ( sHusband != "?" ) 
						{
							sw1.Write(sHusband);
							sw1.Write(" and ");
						}
						if ( sWife != "?" ) 
						{
							sw1.Write(sWife);
						}
						sw1.WriteLine(" are:");
						sw1.WriteLine("<br>");

						//listing children
						sw1.WriteLine("<table border=" + QUOTE + "0" + QUOTE + " cellpadding=" + QUOTE + "7" + QUOTE + " cellspacing=" + QUOTE + "0" + QUOTE + " width=" + QUOTE + "100%" + QUOTE + ">");
						foreach (Child child in MyChildren)
						{
							if ( child.FamilyID == FamRefID ) 
							{
								sLinks  = new ArrayList();
								sLnkFamID = new ArrayList();
								iNumLinks = 0;
								//find out if the child has a family page
								if ( MyIndividuals[child.ChildID].Sex == "M" && MyIndividuals[child.ChildID].HasOwnFamily ) 
								{
									if ( MyIndividuals[child.ChildID].FamList.Count > 0 ) 
									{
										for ( iLinkcount = 0 ; iLinkcount <= MyIndividuals[child.ChildID].FamList.Count - 1 ; iLinkcount++)
										{
											sLnkFamID.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
											sLinks.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
											sLinks[iNumLinks] = sf.Right(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 2);
											sLinks[iNumLinks] = sf.Left(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 1);
											sLinks[iNumLinks] = System.Convert.ToInt32(sLinks[iNumLinks]).ToString("000");
											sLinks[iNumLinks] = configSettings.FamFilePrefix + sLinks[iNumLinks] + ".html";
											iNumLinks++;
										} // iLinkcount
									}
								}
								if ( MyIndividuals[child.ChildID].Sex == "F" && MyIndividuals[child.ChildID].HasOwnFamily ) 
								{
									if ( MyIndividuals[child.ChildID].FamList.Count > 0 ) 
									{
										for ( iLinkcount = 0 ; iLinkcount <= MyIndividuals[child.ChildID].FamList.Count - 1; iLinkcount++)
										{
											sLnkFamID.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
											sLinks.Add(MyIndividuals[child.ChildID].FamList[iLinkcount].FamId);
											sLinks[iNumLinks] = sf.Right(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 2);
											sLinks[iNumLinks] = sf.Left(sLinks[iNumLinks].ToString(), sf.Len(sLinks[iNumLinks].ToString()) - 1);
											sLinks[iNumLinks] = System.Convert.ToInt32(sLinks[iNumLinks]).ToString("000");
											sLinks[iNumLinks] = configSettings.FamFilePrefix + sLinks[iNumLinks] + ".html";
											iNumLinks++;
										} // iLinkcount
									}
								}

								iChildCount = iChildCount + 1;
								sw1.WriteLine("<TR>");
								sw1.WriteLine("<TD valign=" + QUOTE + "top" + QUOTE + " width=" + QUOTE + "66%" + QUOTE + ">");
								sw1.Write(sf.Trim(iChildCount.ToString()) + ". " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname);

								if ( configSettings.DisplayRIN == true ) 
								{
									sw1.Write("&nbsp;(RIN: " + FixRin(MyIndividuals[child.ChildID].ID) + ")");
								}
								if ( configSettings.CreateListReport == true ) 
								{
									sChildName = MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname;
									sw2.WriteLine("{0},{1},{2}", sChildName, MyIndividuals[child.ChildID].ReferenceNumber, sSrnLink);
								}

								if ( MyIndividuals[child.ChildID].LastChangeDate > dtLastChangeDate ) dtLastChangeDate = MyIndividuals[child.ChildID].LastChangeDate;
								//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
								if ( configSettings.CreateGendexFile == true ) 
								{
									//"GENDEX.txt"
									sGenUrl = sSrnLink;
									MyGendices.Add(sGenUrl, sf.UCase(MyIndividuals[child.ChildID].Surname), MyIndividuals[child.ChildID].Forenames + " /" + sf.UCase(MyIndividuals[child.ChildID].Surname) + "/", (MyIndividuals[child.ChildID].BirthDateText), (MyIndividuals[child.ChildID].BirthPlace), (MyIndividuals[child.ChildID].DeathDateText), (MyIndividuals[child.ChildID].DeathPlace), CreateGUIDKey());
								}
								//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


								if ( MyIndividuals[child.ChildID].BirthDateText != "" ) 
								{
									sw1.WriteLine(", b. " + MyIndividuals[child.ChildID].BirthDateText);
								}
								sw1.WriteLine("</TD>");
								sw1.WriteLine("<TD valign=" + QUOTE + "top" + QUOTE + " width=" + QUOTE + "33%" + QUOTE + ">");
								sw1.WriteLine("<FONT SIZE=2><EM>");

								if ( iNumLinks > 0 ) 
								{

									for ( iLinkcount = 0 ; iLinkcount <= iNumLinks - 1; iLinkcount++)
									{
										if ( iLinkcount == 0 ) 
										{
											sw1.WriteLine("See ");
										} 
										else 
										{
											sw1.WriteLine(" OR ");
										}

										sw1.WriteLine("<A HREF=" + QUOTE + sLinks[iLinkcount].ToString() + QUOTE + ">");


										//the husband
										if ( MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband != "?" ) 
										{
											sChHusband = MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Forenames + " " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Surname;
											if ( MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Suffix != "" ) 
											{
												sChHusband += ", " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Husband].Suffix;
											}
										} 
										else 
										{
											sChHusband = "?";
										}

										//the wife
										if ( MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife != "?" ) 
										{
											sChWife = MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Forenames + " " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Surname;
											if ( MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Suffix != "" ) 
											{
												sChWife += ", " + MyIndividuals[MyFamilies[sLnkFamID[iLinkcount].ToString()].Wife].Suffix;
											}
										} 
										else 
										{
											sChWife = "?";
										}

										//title of web page that we are linking to
										sChTitle = sChHusband + " &amp; " + sChWife;

										sw1.WriteLine(sChTitle);
										sw1.WriteLine("</A>");
									} //
								}
								sw1.WriteLine("<FONT>");
								sw1.WriteLine("</TD>");
								sw1.WriteLine("</TR>");
							}
						} // child
						sw1.WriteLine("</TABLE>");
					}


					//--------marriage notes
					iNumEvents = MyFamilies[iFamCount].LifeEvents.Count;
					if ( iNumEvents > 0 || MyFamilies[iFamCount].Notes != "" ) 
					{
						bNotesOkay = true;
						if ( MyFamilies[iFamCount].Husband != "?" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText == Privacy ) 
							{
								bNotesOkay = false;
							}
						}
						if ( MyFamilies[iFamCount].Wife != "?" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText == Privacy ) 
							{
								bNotesOkay = false;
							}
						}

						if ( bNotesOkay == true ) 
						{

							sw1.WriteLine("<HR NOSHADE SIZE=1>");
							bDidLine = true;
							if ( iNumEvents > 0 ) 
							{
								sw1.WriteLine("<P><EM>Marriage Events for " + sHusband + "\\" + sWife + ":</EM></P>");
								sw1.WriteLine("<UL>");
								foreach (LifeEvent ev in MyFamilies[iFamCount].LifeEvents)
								{
									sw1.WriteLine("<LI>");
									sw1.WriteLine(ev.EventText + "&nbsp; ");
									sw1.WriteLine(ev.EventDescription + "&nbsp; ");
									sw1.WriteLine(ev.EventDateString + "&nbsp;");
									sw1.WriteLine(ev.EventPlace + "&nbsp;");
									sw1.WriteLine(ev.EventNote + "&nbsp;");
									sw1.WriteLine("</LI>");
								} // TheEvent
								sw1.WriteLine("</UL>");
							}

							if ( MyFamilies[iFamCount].Notes != "" && configSettings.ExcludeNotes == false ) 
							{
								//if ( MyIndividuals(MyFamilies[iFamCount].Husband).BirthDateText != Privacy ) {
								sw1.WriteLine("<P><EM>Marriage Notes for " + sHusband + "\\" + sWife + ":</EM></P>");
								sw1.WriteLine("<FONT SIZE=2>");
								foreach (Note note in MyNotes)
								{
									if ( note.ID == MyFamilies[iFamCount].Notes ) 
									{
										sw1.WriteLine("<p>" + note.NoteText + "</p>");
									}
								} // note
								sw1.WriteLine("</FONT>");
								//}
							}

						}
					}

					//--------------other marriages?
					NumOtherMarriages = 0;
					if ( MyFamilies[iFamCount].Husband != "?" ) 
					{
						aryOtherFams = GetOtherMarriages(MyFamilies[iFamCount].Husband, MyFamilies[iFamCount].ID);
						if ( aryOtherFams.Count != 0 ) 
						{
							NumOtherMarriages = aryOtherFams.Count - 1;
							if ( bDidLine == false )  sw1.WriteLine("<HR NOSHADE SIZE=1>");
							sw1.WriteLine("<P><EM>Other Marriages for " + sHusband + ":</EM><BR>");
							for ( iOtherCnt = 0 ; iOtherCnt <= NumOtherMarriages; iOtherCnt++)
							{
								sw1.WriteLine(GetOtherLink(aryOtherFams[iOtherCnt].ToString(), iOtherCnt,false));
							} // iOtherCnt
							sw1.WriteLine("</P>");
						}
					}
					NumOtherMarriages = 0;
					if ( MyFamilies[iFamCount].Wife != "?" ) 
					{
						aryOtherFams = GetOtherMarriages(MyFamilies[iFamCount].Wife, MyFamilies[iFamCount].ID);
						if (aryOtherFams.Count != 0) 
						{
							NumOtherMarriages = aryOtherFams.Count - 1;
							if ( bDidLine == false )  sw1.WriteLine("<HR NOSHADE SIZE=1>");
							sw1.WriteLine("<P><EM>Other Marriages for " + sWife + ":</EM><BR>");
							for ( iOtherCnt = 0 ; iOtherCnt <= NumOtherMarriages; iOtherCnt++)
							{
								sw1.WriteLine(GetOtherLink(aryOtherFams[iOtherCnt].ToString(), iOtherCnt,false));
							} // iOtherCnt
							sw1.WriteLine("</P>");
						}
					}
					bDidLine = false;

					//now the notes
					if ( sHusband != "?" ) 
					{

						iNumEvents = MyIndividuals[MyFamilies[iFamCount].Husband].LifeEvents.Count;
						bDidLine = false;

						if ( iNumEvents > 0 || MyIndividuals[MyFamilies[iFamCount].Husband].Notes != "" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<HR NOSHADE SIZE=1>");
								bDidLine = true;
								sw1.WriteLine("<P><EM>Notes for " + sHusband + ":</EM></P>");
							}
						}

						if ( MyIndividuals[MyFamilies[iFamCount].Husband].AliasName != "" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("Also known as: " + MyIndividuals[MyFamilies[iFamCount].Husband].AliasName);
							}
						}

						if ( iNumEvents > 0 ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<UL>");
								foreach (LifeEvent ev in MyIndividuals[MyFamilies[iFamCount].Husband].LifeEvents)
								{
									sw1.WriteLine("<LI>");
									sw1.WriteLine(ev.EventText + "&nbsp; ");
									sw1.WriteLine(ev.EventDescription + "&nbsp; ");
									sw1.WriteLine(ev.EventDateString + "&nbsp;");
									sw1.WriteLine(ev.EventPlace + "&nbsp;");
									sw1.WriteLine(ev.EventNote + "&nbsp;");
									sw1.WriteLine("</LI>");
								} // ev
								if ( MyIndividuals[MyFamilies[iFamCount].Husband].Nationality != "" ) 
								{
									sw1.WriteLine("<LI>");
									sw1.WriteLine("Nationality " + MyIndividuals[MyFamilies[iFamCount].Husband].Nationality);
									sw1.WriteLine("</LI>");
								}
								sw1.WriteLine("</UL>");
							}
						}

						if ( MyIndividuals[MyFamilies[iFamCount].Husband].Notes != "" && configSettings.ExcludeNotes == false ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Husband].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<FONT SIZE=2>");
								foreach (Note note in MyNotes)
								{
									if ( note.ID == MyIndividuals[MyFamilies[iFamCount].Husband].Notes ) 
									{
										sw1.WriteLine("<p>" + note.NoteText + "</p>");
									}
								} // note
								sw1.WriteLine("</FONT>");
							}
						}

						//sources for husband
						iNumSrcs = MyIndividuals[MyFamilies[iFamCount].Husband].Sources.Count;

						if ( iNumSrcs > 0 ) 
						{
							if ( bDidLine == false )  sw1.WriteLine("<HR NOSHADE SIZE=1>");
							sw1.WriteLine("<P><EM>Sources for " + sHusband + ":</EM></P>");
						}


						if ( iNumSrcs > 0 ) 
						{
							sw1.WriteLine("<FONT SIZE=2>");
							sw1.WriteLine("<OL>");
							foreach (Source src in MyIndividuals[MyFamilies[iFamCount].Husband].Sources)
							{
								sw1.Write("<LI>");
								if ( configSettings.FamFilePrefix == "fam" ) 
								{
									sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + src.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
								} 
								else 
								{
									sw1.Write("<EM>" + "<a href=" + QUOTE + configSettings.FamFilePrefix + "_sources.html#" + src.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
								}
								if ( src.Note != "" ) 
								{
									sw1.Write(" Note: " + src.Note + "&nbsp;");
								}
								if ( src.SourceText != "" ) 
								{
									sw1.Write("<em>" + src.SourceText + "</em>");
								}
								sw1.WriteLine("</LI>");
							} // src
							sw1.WriteLine("</OL>");
							sw1.WriteLine("</FONT>");
						}

					}

					//*************NOTES FOR WIFE
					if ( sWife != "?" ) 
					{

						iNumEvents = MyIndividuals[MyFamilies[iFamCount].Wife].LifeEvents.Count;
						bDidLine = false;

						if ( iNumEvents > 0 || MyIndividuals[MyFamilies[iFamCount].Wife].Notes != "" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<HR NOSHADE SIZE=1>");
								bDidLine = true;
								sw1.WriteLine("<P><EM>Notes for " + sWife + ":</EM></P>");
							}
						}

						if ( MyIndividuals[MyFamilies[iFamCount].Wife].AliasName != "" ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("Also known as: " + MyIndividuals[MyFamilies[iFamCount].Wife].AliasName);
							}
						}

						if ( iNumEvents > 0 ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<UL>");
								foreach ( LifeEvent ev in MyIndividuals[MyFamilies[iFamCount].Wife].LifeEvents) 
								{
									sw1.WriteLine("<LI>");
									sw1.WriteLine(ev.EventText + "&nbsp; ");
									sw1.WriteLine(ev.EventDescription + "&nbsp; ");
									sw1.WriteLine(ev.EventDateString + "&nbsp;");
									sw1.WriteLine(ev.EventPlace + "&nbsp;");
									sw1.WriteLine(ev.EventNote + "&nbsp;");
									sw1.WriteLine("</LI>");
								} // ev
								if ( MyIndividuals[MyFamilies[iFamCount].Wife].Nationality != "" ) 
								{
									sw1.WriteLine("<LI>");
									sw1.WriteLine("Nationality " + MyIndividuals[MyFamilies[iFamCount].Wife].Nationality);
									sw1.WriteLine("</LI>");
								}
								sw1.WriteLine("</UL>");
							}
						}

						if ( MyIndividuals[MyFamilies[iFamCount].Wife].Notes != "" && configSettings.ExcludeNotes == false ) 
						{
							if ( MyIndividuals[MyFamilies[iFamCount].Wife].BirthDateText != Privacy ) 
							{
								sw1.WriteLine("<FONT SIZE=2>");
								foreach (Note note in MyNotes)
								{
									if ( note.ID == MyIndividuals[MyFamilies[iFamCount].Wife].Notes ) 
									{
										sw1.WriteLine("<p>" + note.NoteText + "</p>");
									}
								} // note
								sw1.WriteLine("</FONT>");
							}
						}

						//sources for wife
						iNumSrcs = MyIndividuals[MyFamilies[iFamCount].Wife].Sources.Count;

						if ( iNumSrcs > 0 ) 
						{
							if ( bDidLine == false ) sw1.WriteLine("<HR NOSHADE SIZE=1>");
							sw1.WriteLine("<P><EM>Sources for " + sWife + ":</EM></P>");
						}


						if ( iNumSrcs > 0 ) 
						{
							sw1.WriteLine("<FONT SIZE=2>");
							sw1.WriteLine("<OL>");
							foreach (Source src in MyIndividuals[MyFamilies[iFamCount].Wife].Sources)
							{
								sw1.Write("<LI>");
								if ( configSettings.FamFilePrefix == "fam" ) 
								{
									sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + src.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
								} 
								else 
								{
									sw1.Write("<EM>" + "<a href=" + QUOTE + configSettings.FamFilePrefix + "_sources.html#" + src.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[src.ID].Title + "</a>, " + "</EM>" + src.Page);
								}
								if ( src.Note != "" ) 
								{
									sw1.Write(" Note: " + src.Note);
								}
								if ( src.SourceText != "" ) 
								{
									sw1.Write("<em>" + src.SourceText + "</em>");
								}
								sw1.WriteLine("</LI>");
							} // src
							sw1.WriteLine("</OL>");
							sw1.WriteLine("</FONT>");
						}
					}

					//------------print notes for children without family records
					foreach (Child child in MyChildren)
					{
						if ( child.FamilyID == FamRefID ) 
						{

							if ( MyIndividuals[child.ChildID].HasOwnFamily == false ) 
							{
								//print the child//s notes on this page (this change decreased proc time by 30%)
								iNumEvents = MyIndividuals[child.ChildID].LifeEvents.Count;

								bDoNotes = false;
								if ( iNumEvents > 0 ) bDoNotes = true;
								if ( MyIndividuals[child.ChildID].Notes != "" ) bDoNotes = true;
								if ( MyIndividuals[child.ChildID].BirthDateText != "" ) bDoNotes = true;
								if ( MyIndividuals[child.ChildID].BirthDateText == Privacy ) bDoNotes = false;

								bDidLine = false;
								//if we can print notes then print the notes
								if ( bDoNotes ) 
								{
									sw1.WriteLine("<HR NOSHADE SIZE=1>");
									bDidLine = true;
									sw1.WriteLine("<P><EM>Notes for " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname + ":</EM></P>");

									if ( MyIndividuals[child.ChildID].AliasName != "" ) 
									{
										if ( MyIndividuals[child.ChildID].BirthDateText != Privacy ) 
										{
											sw1.WriteLine("Also known as: " + MyIndividuals[child.ChildID].AliasName);
										}
									}

									sw1.WriteLine("<UL>");
									if ( MyIndividuals[child.ChildID].BirthDateText != "" ) 
									{
										if ( sf.IsDate(MyIndividuals[child.ChildID].BirthDateText) ) 
										{
											sw1.Write("<LI>Born  " + sf.DateValue(MyIndividuals[child.ChildID].BirthDateText).ToString("MMMM dd,yyyy"));
										} 
										else 
										{
											sw1.Write("<LI>Born  " + MyIndividuals[child.ChildID].BirthDateText);
										}
									}
									if ( MyIndividuals[child.ChildID].BirthPlace != "" ) 
									{
										sw1.Write(" in " + FixEstLoc((MyIndividuals[child.ChildID].BirthPlace)));
										sw1.WriteLine(". </LI>");
									} 
									else 
									{
										sw1.WriteLine(". </LI>");
									}

									if ( MyIndividuals[child.ChildID].DeathDateText != "" || MyIndividuals[child.ChildID].DeathPlace != "" ) 
									{
										sw1.Write("<LI>Died " + MyIndividuals[child.ChildID].DeathDateText);
										if ( MyIndividuals[child.ChildID].DeathPlace != "" ) 
										{
											sw1.WriteLine(" in " + FixEstLoc((MyIndividuals[child.ChildID].DeathPlace)) + "</LI>");
										}
										sw1.WriteLine(". </LI>");
									}

									if ( iNumEvents > 0 ) 
									{
										if ( MyIndividuals[child.ChildID].BirthDateText != Privacy ) 
										{
											foreach (LifeEvent TheEvent in MyIndividuals[child.ChildID].LifeEvents)
											{
												//allow birth and death are recorded as events
												//they are handled separately (see above)
												if (TheEvent.EventText != "Birth" && TheEvent.EventText != "Death")
												{
													sw1.WriteLine("<LI>");
													sw1.WriteLine(TheEvent.EventText + "&nbsp; ");
													sw1.WriteLine(TheEvent.EventDescription + "&nbsp; ");
													sw1.WriteLine(TheEvent.EventDateString + "&nbsp;");
													sw1.WriteLine(TheEvent.EventPlace + "&nbsp;");
													sw1.WriteLine(TheEvent.EventNote + "&nbsp;");
													sw1.WriteLine("</LI>");
												}
											} // TheEvent

											if ( MyIndividuals[child.ChildID].Nationality != "" ) 
											{
												sw1.WriteLine("<LI>");
												sw1.WriteLine("Nationality " + MyIndividuals[child.ChildID].Nationality);
												sw1.WriteLine("</LI>");
											}
										}
									}
									sw1.WriteLine("</UL>");

									if ( MyIndividuals[child.ChildID].Notes != "" && configSettings.ExcludeNotes == false ) 
									{
										if ( MyIndividuals[child.ChildID].BirthDateText != Privacy ) 
										{
											sw1.WriteLine("<FONT SIZE=2>");
											foreach (Note note in MyNotes)
											{
												if ( note.ID == MyIndividuals[child.ChildID].Notes ) 
												{
													sw1.WriteLine("<p>" + note.NoteText + "</p>");
												}
											} // note
											sw1.WriteLine("</FONT>");
										}
									}
								} //end of notes

								//**********how about sources for this child?
								//**********added ver 3.01
								iNumSrcs = MyIndividuals[child.ChildID].Sources.Count;

								if ( iNumSrcs > 0 ) 
								{
									if ( bDidLine == false ) sw1.WriteLine("<HR NOSHADE SIZE=1>");
									sw1.WriteLine("<P><EM>Sources for " + MyIndividuals[child.ChildID].Forenames + " " + MyIndividuals[child.ChildID].Surname + ":</EM></P>");
								}


								if ( iNumSrcs > 0 ) 
								{
									sw1.WriteLine("<FONT SIZE=2>");
									sw1.WriteLine("<OL>");
									foreach (Source TheSource in MyIndividuals[child.ChildID].Sources)
									{
										sw1.Write("<LI>");
										if ( configSettings.FamFilePrefix == "fam" ) 
										{
											sw1.Write("<EM>" + "<a href=" + QUOTE + "sources.html#" + TheSource.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[TheSource.ID].Title + "</a>, " + "</EM>" + TheSource.Page);
										} 
										else 
										{
											sw1.Write("<EM>" + "<a href=" + QUOTE + configSettings.FamFilePrefix + "_sources.html#" + TheSource.ID + QUOTE + " target=" + QUOTE + "_blank" + QUOTE + ">" + MySources[TheSource.ID].Title + "</a>, " + "</EM>" + TheSource.Page);
										}
										if ( TheSource.Note != "" ) 
										{
											sw1.Write(" Note: " + TheSource.Note);
										}
										if ( TheSource.SourceText != "" ) 
										{
											sw1.Write("<em>" + TheSource.SourceText + "</em>");
										}
										sw1.WriteLine("</LI>");
									} // TheSource
									sw1.WriteLine("</OL>");
									sw1.WriteLine("</FONT>");
								}
								//********************end of sources for child
							}
						}
					} // child

					if ( dtLastChangeDate > System.DateTime.FromOADate(0) && configSettings.MostRecentOnPage == true ) 
					{
						sw1.WriteLine("<HR NOSHADE SIZE=1>");
						sw1.WriteLine("<p><center><em>The most recent update of information contained on this page was on:</em>&nbsp;" + dtLastChangeDate.ToString("dd MMMM yyyy") + "</center></p>");
					}
					sw1.WriteLine("<HR NOSHADE SIZE=1>");
					sw1.WriteLine("<EM><CENTER>");
					if ( configSettings.FamFilePrefix == "fam" ) 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
					} 
					else 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
					}
					sw1.WriteLine("Index");
					sw1.WriteLine("</A>");
					sw1.WriteLine("</CENTER></EM>");
					sw1.WriteLine("<EM><CENTER>");
					if ( configSettings.FamFilePrefix == "fam" ) 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + "surnames.html" + QUOTE + ">");
					} 
					else 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_surnames.html" + QUOTE + ">");
					}
					sw1.WriteLine("Surnames");
					sw1.WriteLine("</A>");
					sw1.WriteLine("</CENTER></EM>");
					sw1.WriteLine("<EM><CENTER>");
					if ( configSettings.FamFilePrefix == "fam" ) 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
					} 
					else 
					{
						sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
					}
					sw1.WriteLine("Table Of Contents");
					sw1.WriteLine("</A>");

					sw1.WriteLine("</CENTER></EM>");
					sw1.WriteLine("<HR NOSHADE SIZE=1>");

					if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
					{
						sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
						sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString() + "&nbsp;");
						if ( configSettings.AuthorsEmail != "" )  sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
						sw1.Write(configSettings.AuthorsName);
						if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
						sw1.WriteLine("</CENTER></P></FONT>");
					}

					sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
					sw1.WriteLine("This page was created on " + DateTime.Now.ToShortDateString() + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
					sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
					sw1.WriteLine("</CENTER></P></FONT>");

					sw1.WriteLine("</BODY>");
					sw1.WriteLine("</HTML>");

					sw1.Close();
					fs1.Close();
				} // iFamCount

				if ( configSettings.CreateListReport == true ) 
				{
					sw2.Close();
					fs2.Close();
				}

				return true;

			BUILDFAMILY_EXIT:
				sw1.Close();
				fs1.Close();
				if ( configSettings.CreateListReport == true ) 
				{
					sw2.Close();
					fs2.Close();
				}
				
				return true;

			}
			catch (Exception ex)
			{
			
				Tools.Logit("The following error occured in BuildFamilyPages while processing the GEDCOM file:" + '\n' + '\r' + "Error: " + ex.Message);
				Tools.Logit("Incomplete");
			
				try
				{
					sw1.Close();
					fs1.Close();
					if ( configSettings.CreateListReport == true ) 
					{
						sw2.Close();
						fs2.Close();
					}
					return false;
				} 
				catch {return false;}
			}

		}

		
		/// <summary>
		/// Summary of BuildIndexEach.
		/// </summary>
		/// 		
		private void BuildIndexEach() 
		{
			string  sFile;
			int iIndCount;
			int iNumInds;
			ArrayList sLinks = new ArrayList();
			string  sLink;
			string  sFullName;
			string  sCurrChar;
			string  sPrevChar;
			string  sUpdate;
			DateTime DaysAgo90;
			FileStream fs1;
			StreamWriter sw1;

			iNumInds = MyIndividuals.Count;
			sLinks.Capacity = iNumInds + 1;
			
			for ( iIndCount = 0 ; iIndCount <= iNumInds - 1; iIndCount++)
			{
				sLinks.Add("");
			}

			SortedList  sl = new SortedList(iNumInds);

			char QUOTE = '"';

			DaysAgo90 = DateTime.Now.AddDays(-90);

			if ( iNumInds == 0 ) return; 

			sl.Clear();

			iIndCount = 0;
			foreach ( Individual individual in MyIndividuals)
			{
				sFullName = sf.UCase(individual.Surname) + ", " + individual.Forenames;
				if ( individual.Suffix != "" ) 
				{
					sFullName = sFullName + ", " + individual.Suffix;
				}

				sFullName = sFullName + "</A></td><td width=" + QUOTE + "30%" + QUOTE + ">";

				if ( individual.BirthDateText != "" && individual.BirthDateText != Privacy ) 
				{
					sFullName = sFullName + individual.BirthDateText;
				}

				sFullName = sFullName + "</td><td width=" + QUOTE + "30%" + QUOTE + ">";

				if ( individual.LastChangeDate != System.DateTime.FromOADate(0) && configSettings.MostRecentOnIndex == true ) 
				{
					sUpdate = "";
					if ( configSettings.HiLiteMostRecent && individual.LastChangeDate > DaysAgo90 ) 
					{
						sUpdate = "<b>";
					}
					sUpdate = sUpdate + individual.LastChangeDate.ToString("dd MMM yyyy");
					if ( configSettings.HiLiteMostRecent && individual.LastChangeDate > DaysAgo90 ) 
					{
						sUpdate = sUpdate + "</b>";
					}
					sFullName = sFullName + sUpdate;
				}

				sFullName = sFullName + "</td>";
				
				//find out which family page they go own
				//==========4.00.4097 optimization
				if ( individual.HasOwnFamily == true ) 
				{
					if (individual.FamList[0].FamId.Length != 0)
					{

						sLinks[iIndCount] =  individual.FamList[0].FamId;
						sLinks[iIndCount] = sf.Right(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 2);
						int iLinkNumber = System.Convert.ToInt32(sf.Left(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 1));
						sLinks[iIndCount] = iLinkNumber.ToString("000");
						sLinks[iIndCount] = configSettings.FamFilePrefix + sLinks[iIndCount].ToString() + ".html";
						if ( sLinks[iIndCount].ToString() != "" ) 
						{
							sl.Add(sFullName + CreateGUIDKey(), iIndCount);
							individual.LinkPage = sLinks[iIndCount].ToString();
						}
					}
				} 
				else 
				{
					if ( individual.FamilyID.Length != 0  )
					{					
						sLinks[iIndCount] =  individual.FamilyID;
						sLinks[iIndCount] = sf.Right(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 2);
						int iLinkNumber = System.Convert.ToInt32(sf.Left(sLinks[iIndCount].ToString(), sf.Len(sLinks[iIndCount].ToString()) - 1));
						sLinks[iIndCount] = iLinkNumber.ToString("000");
						sLinks[iIndCount] = configSettings.FamFilePrefix + sLinks[iIndCount].ToString() + ".html";
						if ( sLinks[iIndCount].ToString() != "" ) 
						{
							sl.Add(sFullName + CreateGUIDKey(), iIndCount);
							individual.LinkPage = sLinks[iIndCount].ToString();
						}
					}
				}
				iIndCount++;
			} // individual

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\ind_idx.html";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_ind_idx.html";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			//file header
			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>Index Of Individuals</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<CENTER>");
			sw1.WriteLine("<a href=" + QUOTE + "#A" + QUOTE + ">A</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#B" + QUOTE + ">B</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#C" + QUOTE + ">C</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#D" + QUOTE + ">D</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#E" + QUOTE + ">E</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#F" + QUOTE + ">F</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#G" + QUOTE + ">G</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#H" + QUOTE + ">H</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#I" + QUOTE + ">I</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#J" + QUOTE + ">J</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#K" + QUOTE + ">K</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#L" + QUOTE + ">L</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#M" + QUOTE + ">M</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#N" + QUOTE + ">N</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#O" + QUOTE + ">O</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#P" + QUOTE + ">P</a>&nbsp;");

			sw1.WriteLine("<a href=" + QUOTE + "#Q" + QUOTE + ">Q</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#R" + QUOTE + ">R</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#S" + QUOTE + ">S</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#T" + QUOTE + ">T</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#U" + QUOTE + ">U</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#V" + QUOTE + ">V</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#W" + QUOTE + ">W</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#X" + QUOTE + ">X</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#Y" + QUOTE + ">Y</a>&nbsp;");
			sw1.WriteLine("<a href=" + QUOTE + "#Z" + QUOTE + ">Z</a>&nbsp;");
			sw1.WriteLine("</CENTER>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sPrevChar = "#";
			for ( iIndCount = 0 ; iIndCount <= iNumInds - 1; iIndCount++)
			{
				if ( _didCancel ) return;
				if ( iIndCount < sl.Count) 
				{
					sFullName = sf.Left((string)sl.GetKey(iIndCount), sf.Len((string)sl.GetKey(iIndCount)) - 36); //strip off GUID;
				} 
				else 
				{
					sFullName = "";
				}

				if ( sFullName != "" ) 
				{
					sLink = sLinks[(int)sl.GetByIndex(iIndCount)].ToString();
					sCurrChar = sf.UCase(sf.Left(sf.Trim(sFullName), 1));
					if ( sPrevChar != sCurrChar ) 
					{
						if ( System.Convert.ToChar(sCurrChar) >= 'A')  
						{
							sw1.WriteLine("</TABLE>");//end the previous table;
							sw1.WriteLine("<EM><CENTER>" + "<A HREF=" + QUOTE + "#TOP" + QUOTE + ">" + "Top</A></CENTER></EM>");
							sw1.WriteLine("<HR NOSHADE SIZE=1>");
						}
						sw1.WriteLine("<H2><A NAME=" + QUOTE + sCurrChar + QUOTE + ">");
						sw1.WriteLine(sCurrChar);
						sw1.WriteLine("</A></H2><BR>");
						sPrevChar = sCurrChar;
						//start a new table
						sw1.WriteLine("<table border=" + QUOTE + "0" + QUOTE + " cellpadding=" + QUOTE + "1" + QUOTE + " cellspacing=" + QUOTE + "1" + QUOTE + " width=" + QUOTE + "100%" + QUOTE + " > ");
						
						if (configSettings.MostRecentOnIndex == true )
						{
							sw1.WriteLine("<tr><th width=" + QUOTE + "40%" + QUOTE + "><em>Name</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Date Of Birth</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Last Updated</em></td><tr>");
						} 
						else 
						{
							sw1.WriteLine("<tr><th width=" + QUOTE + "40%" + QUOTE + "><em>Name</em></td><th width=" + QUOTE + "30%" + QUOTE + "><em>Date Of Birth</em></td><tr>");
						}
					}
					sw1.Write("<tr><td width=" + QUOTE + "40%" + QUOTE + "><A HREF=" + QUOTE + sLink + QUOTE + ">");
					sw1.Write(sFullName);
					sw1.WriteLine("</TR>");
				}
			} // iIndCount

			sw1.WriteLine("</TABLE>");//end the last table;
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>" + "<A HREF=" + QUOTE + "#TOP" + QUOTE + ">" + "Top</A></CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "surnames.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_surnames.html" + QUOTE + ">");
			}
			sw1.WriteLine("Surnames");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.Year.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			sw1.Close();
			fs1.Close();
		}

		
		/// <summary>
		/// Summary of BuildBiblio.
		/// </summary>
		/// 		
		private void BuildBiblio() 
		{
			// int lFn;
			string  sFile;
			//			string  sData;
			int iSrcCount;
			int iNumSrcs;
			//			Source MySource;
			//string  QUOTE;
			FileStream fs1;
			StreamWriter sw1;

			//MainForm.pbFile.value = 0

			iNumSrcs = MySources.Count;

			char QUOTE = '"';

			if ( iNumSrcs == 0 ) return;

			//lFn = FreeFile()

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\sources.html";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_sources.html";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			//file header
			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>Bibliography</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<CENTER>");
			sw1.WriteLine("<H1>Bibliography</H1>");
			sw1.WriteLine("</CENTER>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<OL>");

			for ( iSrcCount = 0 ; iSrcCount <= iNumSrcs - 1; iSrcCount++)
			{
				if ( _didCancel ) goto BUILDBIBLIO_EXIT;
				if ( MySources[iSrcCount].Author != "" ) 
				{
					sw1.Write("<LI>" + MySources[iSrcCount].Author + ",&nbsp;<EM>");
				} 
				else 
				{
					sw1.Write("<LI>");
				}

				sw1.Write("<a name=" + MySources[iSrcCount].ID + ">" + MySources[iSrcCount].Title + "</a>");

				if ( MySources[iSrcCount].Author != "" ) 
				{
					sw1.Write("</EM>");
				}

				if ( MySources[iSrcCount].PublicationInfo != "" ) 
				{
					sw1.Write(",&nbsp;" + MySources[iSrcCount].PublicationInfo);
				}
				if ( MySources[iSrcCount].Media != "" ) 
				{
					sw1.Write(",&nbsp;[" + MySources[iSrcCount].Media + "]");
				}
				if ( MySources[iSrcCount].Note != "" ) 
				{
					sw1.Write("&nbsp;<font size=2>(" + MySources[iSrcCount].Note + ")</font>");
				}
				sw1.WriteLine("<br></LI>");
			} // iSrcCount

			sw1.WriteLine("</OL>");

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" ) sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" ) sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			BUILDBIBLIO_EXIT:;
			sw1.Close();
			fs1.Close();
		}

		
		/// <summary>
		/// Summary of BuildSurnamePage.
		/// </summary>
		/// 		
		private void BuildSurnamePage() 
		{
			string  sFile;
			int iSrnCount;
			int iNumSrns;
			string  sLink;
			string  sFamilyName;
			string  sItemCnt;
			ArrayList sLinks = new ArrayList();
			ArrayList iSrnCnt = new ArrayList();
			FileStream fs1;
			StreamWriter sw1;
			Surname NewSurname;

			//moved here in 0.7 count all of the surnames
			for(int i = 0; i <= MyIndividuals.Count - 1; i++)
			{
				NewSurname = new Surname();
				NewSurname.FamilyName = sf.UCase(MyIndividuals[i].Surname);
				NewSurname.FirstLink = MyIndividuals[i].LinkPage;
				if ( MySurnames.Add(NewSurname) == false ) 
				{
					//if it failed to add then increment it
					MySurnames[NewSurname.FamilyName].NumItems = MySurnames[NewSurname.FamilyName].NumItems + 1;
				}
				NewSurname = null;
			}

			iNumSrns = MySurnames.Count;

			char QUOTE = '"';

			if ( iNumSrns == 0 ) return;

			SortedList  sl = new SortedList(iNumSrns);
			
			//put in sorted list for quick and dirty sort
			sl.Clear();

			for ( iSrnCount = 0 ; iSrnCount <= iNumSrns - 1; iSrnCount++)
			{
				sl.Add(MySurnames[iSrnCount].FamilyName + CreateGUIDKey(), iSrnCount);
				sLinks.Add(MySurnames[iSrnCount].FirstLink);
				iSrnCnt.Add(MySurnames[iSrnCount].NumItems);
			} // iSrnCount


			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\surnames.html";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_surnames.html";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			//file header
			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>Surnames</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + "Generator" + QUOTE + " CONTENT=" + QUOTE + "UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<CENTER>");
			sw1.WriteLine("<H1>Surnames</H1>");
			sw1.WriteLine("</CENTER>");
			sw1.WriteLine("<EM><CENTER>");
			sw1.WriteLine("<FONT SIZE=2>");
			sw1.Write("The database is arranged in ascending order, beginning with the primary individual and branching out towards ");
			sw1.Write("the ancestors of the primary individual. The surname links follow this pattern such that selecting a surname will ");
			sw1.Write("take you to the first appearance of that surname on the branch leading from the primary individual. This does not mean ");
			sw1.Write("that this is the only appearance of this surname and it is suggested that you follow links within the database or make use ");
			sw1.WriteLine("of the index for finding more details.");
			sw1.WriteLine("</FONT>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<OL>");

			for ( iSrnCount = 0 ; iSrnCount <= iNumSrns - 1; iSrnCount++)
			{
				sFamilyName = sf.Left((string)sl.GetKey(iSrnCount), sf.Len((string)sl.GetKey(iSrnCount)) - 36); //strip off GUID;
				if ( sf.Trim(sFamilyName) != "" ) 
				{
					sLink = sLinks[(int)sl.GetByIndex(iSrnCount)].ToString();
					sItemCnt = iSrnCnt[(int)sl.GetByIndex(iSrnCount)].ToString();
					sw1.WriteLine("<A HREF=" + QUOTE + sLink + QUOTE + ">" + sFamilyName + "</A>");
					if ( configSettings.AddSurnameCount == true ) sw1.WriteLine("(" + sItemCnt + ")");
					sw1.WriteLine(",&nbsp; ");
				}
			} // iSrnCount

			sw1.WriteLine("</OL>");

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			sw1.Close();
			fs1.Close();

		}


		/// <summary>
		/// Summary of BuildTableOfContents.
		/// </summary>
		/// 		
		private void BuildTableOfContents() 
		{
			string  sFile;
			//			string  QUOTE;
			string  sFirstFile;
			int iCnt;
			string  sSurname;
			FileStream fs1;
			StreamWriter sw1;

			char QUOTE = '"';

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\index.htm";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_index.htm";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			sw1.WriteLine("<HTML>");

			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>" + configSettings.MainPageTitle + "</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + "Generator" + QUOTE + " CONTENT=" + QUOTE + "UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");


			//optionally add keywords to page
			//if the surname count is greater that five, add it
			if ((configSettings.AddKeywords == true) ) 
			{
				sw1.Write("<META NAME=" + QUOTE + "keywords" + QUOTE + " CONTENT=" + QUOTE + "genealogy,geneology,GENEALOGY,GENEOLOGY,ancestry,family history,heritage,family tree");
				for ( iCnt = 0 ; iCnt <= MySurnames.Count - 1; iCnt++)
				{ //- 1
					sSurname = sf.Trim(MySurnames[iCnt].FamilyName);
					if ( sSurname != "" && MySurnames[iCnt].NumItems > 5 ) 
					{
						sw1.Write("," + sSurname);
					}
				} // iCnt
				sw1.WriteLine(QUOTE + ">");

				sw1.WriteLine("<META HTTP-EQUIV=" + QUOTE + "keywords" + QUOTE + " CONTENT=" + QUOTE + "genealogy geneology GENEALOGY GENEOLOGY ancestry family history heritage family tree" + QUOTE + ">");
			}

			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<H1>" + configSettings.MainPageTitle + "</H1>");
			sw1.WriteLine("</CENTER><CENTER>Last updated " + DateTime.Now.ToString("MMMM dd, yyyy") + "</CENTER><HR>");
			sw1.WriteLine("<H2>Table of Contents</H2>");
			sw1.WriteLine("<UL>");
			sFirstFile = configSettings.FamFilePrefix + localSettings.FirstFamily.ToString("000") + ".html";
			sw1.WriteLine("<LI><A HREF=" + QUOTE + sFirstFile + QUOTE + ">Family Pages</A>");

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine(" <LI><A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">Index of Names</A>");
			} 
			else 
			{
				sw1.WriteLine(" <LI><A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">Index of Names</A>");
			}

			if ( MySources.Count > 0 ) 
			{
				if ( configSettings.FamFilePrefix == "fam" ) 
				{
					sw1.WriteLine("<LI><A HREF=" + QUOTE + "sources.html" + QUOTE + ">Sources (Bibliography)</A>");
				} 
				else 
				{
					sw1.WriteLine("<LI><A HREF=" + QUOTE + configSettings.FamFilePrefix + "_sources.html" + QUOTE + ">Sources (Bibliography)</A>");
				}
			}
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<LI><A href=" + QUOTE + "surnames.html" + QUOTE + ">Surnames</A>");
			} 
			else 
			{
				sw1.WriteLine("<LI><A href=" + QUOTE + configSettings.FamFilePrefix + "_surnames.html" + QUOTE + ">Surnames</A>");
			}
			if ( configSettings.CreateStatsPage == true ) 
			{
				if ( configSettings.FamFilePrefix == "fam" ) 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + "stats.htm" + QUOTE + ">Statistics</A>");
				} 
				else 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + configSettings.FamFilePrefix + "_stats.htm" + QUOTE + ">Statistics</A>");
				}
			}
			if ( configSettings.CreateChronoPage == true ) 
			{
				if ( configSettings.FamFilePrefix == "fam" ) 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + "chrono.htm" + QUOTE + ">Chronology Of Events</A>");
				} 
				else 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + configSettings.FamFilePrefix + "_chrono.htm" + QUOTE + ">Chronology Of Events</A>");
				}
			}
			if ( configSettings.CreateLocPage == true ) 
			{
				if ( configSettings.FamFilePrefix == "fam" ) 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + "locations.html" + QUOTE + ">List Of Locations && Place Names</A>");
				} 
				else 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + configSettings.FamFilePrefix + "_locations.html" + QUOTE + ">List Of Locations && Place Names</A>");
				}
			}
			if ( configSettings.CreateOccupationsPage == true ) 
			{
				if ( configSettings.FamFilePrefix == "fam" ) 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + "occupations.html" + QUOTE + ">Occupations</A>");
				} 
				else 
				{
					sw1.WriteLine("<LI><A href=" + QUOTE + configSettings.FamFilePrefix + "_occupations.html" + QUOTE + ">Occupations</A>");
				}
			}
			sw1.WriteLine("</LI>");
			sw1.WriteLine("</UL>");
			sw1.WriteLine("<HR>");
			if ( configSettings.AuthorsUrl != "" ) 
			{
				sw1.WriteLine("<center><a href=" + QUOTE + configSettings.AuthorsUrl + QUOTE + "Main Page</a></center>");
			}
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			sw1.Close();
			fs1.Close();

		}

		/// <summary>
		/// Summary of BuildStatisticsPage.
		/// </summary>
		/// 		
		private void BuildStatisticsPage() 
		{
			string  sFile;
			//			string  QUOTE;
			//			string  sFirstFile;
			int iCnt;
			//			string  sSurname;
			FileStream fs1;
			StreamWriter sw1;

			float sngSources;
			float sngNotes;
			int iMissBirthDate = 0;
			int iMissBirthPlace = 0;
			int iPartBirthdate = 0;
			int iMissDeathDate = 0;
			int iPartDeathDate = 0;
			int iMissDeathPlace = 0;
			int NumInds;
			float sngStat;
			MoreStats  myMoreStats = new MoreStats();

			char QUOTE = '"';

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\stats.htm";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_stats.htm";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			sw1.WriteLine("<html>");
			sw1.WriteLine("<head>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<title>Statistics for Family Database</title>");
			sw1.WriteLine("</head>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<center><h1>Statistics for ( Family Database</h1><center>");
			sw1.WriteLine("<div align=" + QUOTE + "left" + QUOTE + ">");
			sw1.WriteLine("<TABLE BORDER=" + QUOTE + "0" + QUOTE + " CELLPADDING=" + QUOTE + "0" + QUOTE + " CELLSPACING=" + QUOTE + "0" + QUOTE + " WIDTH=" + QUOTE + "100%" + QUOTE + ">");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.Source + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source Name:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SourceName + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Source Version:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.Version + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Creation Date:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.CreationDate + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Creation Time:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.CreationTime + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">GEDCOM File Name:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SourceFile + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Submitter Name:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SubmitterName + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Submitter E-mail:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFileInfo.SubmitterEmail + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Individuals:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyIndividuals.Count.ToString() + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Families:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyFamilies.Count.ToString() + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Notes:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MyNotes.Count.ToString() + "</td>");
			sw1.WriteLine("</TR>");
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Number Of Sources:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + MySources.Count.ToString() + "</td>");
			sw1.WriteLine("</TR>");

			if ( MyNotes.Count > 0 ) 
			{
				sngNotes = (float)MyNotes.Count / MyIndividuals.Count;
				sw1.WriteLine("<TR>");
				sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Notes / Individuals:</td>");
				sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngNotes.ToString("#,##0.00;;;Nil") + "</td>");
				sw1.WriteLine("</TR>");
			} 
			else 
			{
				sw1.WriteLine("<TR>");
				sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Notes / Individuals:</td>");
				sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">0</td>");
				sw1.WriteLine("</TR>");
			}

			if ( MySources.Count > 0 ) 
			{
				sngSources = (float)MySources.Count / MyIndividuals.Count;
				sw1.WriteLine("<TR>");
				sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Sources / Individuals:</td>");
				sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngSources.ToString("#,##0.00;;;Nil") + "</td>");
				sw1.WriteLine("</TR>");
			} 
			else 
			{
				sw1.WriteLine("<TR>");
				sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + ">Sources / Individuals:</td>");
				sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">0</td>");
				sw1.WriteLine("</TR>");
			}

			NumInds = MyIndividuals.Count;

			if ( NumInds > 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= NumInds - 1; iCnt++)
				{
					if ( sf.Trim(MyIndividuals[iCnt].BirthDateText) == "" )  iMissBirthDate = iMissBirthDate + 1;
					if ( sf.IsDate(MyIndividuals[iCnt].BirthDateText) == false && sf.Trim(MyIndividuals[iCnt].BirthDateText) != "" )  iPartBirthdate = iPartBirthdate + 1;
					if ( sf.Trim(MyIndividuals[iCnt].DeathDateText) == "" )  iMissDeathDate = iMissDeathDate + 1;
					if ( sf.IsDate(MyIndividuals[iCnt].DeathDateText) == false && sf.Trim(MyIndividuals[iCnt].DeathDateText) != "" )  iPartDeathDate = iPartDeathDate + 1;
					if ( sf.Trim(MyIndividuals[iCnt].BirthPlace) == "" )  iMissBirthPlace = iMissBirthPlace + 1;
					if ( sf.Trim(MyIndividuals[iCnt].DeathPlace) == "" )  iMissDeathPlace = iMissDeathPlace + 1;
				} // iCnt
			}

			sngStat = (float)iMissBirthDate / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing BirthDates:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			sngStat = (float)iPartBirthdate / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Partial BirthDates:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			sngStat = (float)iMissBirthPlace / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Birth Place:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			sngStat = (float)iMissDeathDate / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Death Dates:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			sngStat = (float)iPartDeathDate / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Partial Death Dates::</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			sngStat = (float)iMissDeathPlace / MyIndividuals.Count;
			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> % Missing Death Place:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + sngStat.ToString("#,##0.00;;;Nil") + "</td>");
			sw1.WriteLine("</TR>");

			myMoreStats = GetMoreStats();

			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born Before 1600:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBornBefore1600.ToString() + "</td>");
			sw1.WriteLine("</TR>");

			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 17th C.:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn17thCentury.ToString() + "</td>");
			sw1.WriteLine("</TR>");

			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 18th C.:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn18thCentury.ToString() + "</td>");
			sw1.WriteLine("</TR>");

			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 19th C.:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn19thCentury.ToString() + "</td>");
			sw1.WriteLine("</TR>");

			sw1.WriteLine("<TR>");
			sw1.WriteLine("<td width=" + QUOTE + "25%" + QUOTE + "> Born in 20th C.:</td>");
			sw1.WriteLine("<td width=" + QUOTE + "75%" + QUOTE + ">" + myMoreStats.CountBorn20thCentury.ToString() + "</td>");
			sw1.WriteLine("</TR>");


			sw1.WriteLine("</TABLE>");
			sw1.WriteLine("</div>");

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			sw1.Close();
			fs1.Close();

		}


		/// <summary>
		/// Summary of BuildTimeLinePage.
		/// </summary>
		/// 		
		private void BuildTimeLinePage() 
		{
			string  FilePath;
			int iYear;
			string  sActualDate;
			string  sIndexDate;
			DateTime dtDummyDate;
			FileStream fs1;
			StreamWriter sw1;

			int iCnt;
			int iNumItems;

			GetTimeLineEvents();

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				FilePath = configSettings.HtmlPath + "\\chrono.htm";
			} 
			else 
			{
				FilePath = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_chrono.htm";
			}

			char Q = '"';
			iYear = 0;


			iNumItems = MyTimeLineEntries.Count;
			SortedList  sl = new SortedList(iNumItems);

			for ( iCnt = 0 ; iCnt <= iNumItems - 1; iCnt++)
			{
				if ( MyTimeLineEntries[iCnt].ActualDate == System.DateTime.FromOADate(0) ) 
				{
					dtDummyDate = sf.DateValue("12/31/" + MyTimeLineEntries[iCnt].TheYear.ToString());
					sIndexDate = dtDummyDate.ToString("yyyyMMdd");
				} 
				else 
				{
					sIndexDate = MyTimeLineEntries[iCnt].ActualDate.ToString("yyyyMMdd");
				}
				sl.Add(sIndexDate + CreateGUIDKey(), iCnt);
			} //

			fs1 = new FileStream(FilePath, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<META NAME=" + Q + "GENERATOR" + Q + " Content=" + Q + "Microsoft Visual Studio 6.0" + Q + ">");
			sw1.WriteLine("<TITLE>Chronology Of Events</TITLE>");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + Q + configSettings.BackgroundFile + Q + " link=" + Q + "#0000FF" + Q + " vlink=" + Q + "#800080" + Q + " bgproperties=" + Q + "fixed" + Q + " leftmargin=" + Q + "100" + Q + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + Q + "#0000FF" + Q + " vlink=" + Q + "#800080" + Q + " bgproperties=" + Q + "fixed" + Q + " leftmargin=" + Q + "100" + Q + ">");
			}
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + Q + "center" + Q + "><img src=" + Q + configSettings.BannerFile + Q + " width=" + Q + "224" + Q + " height=" + Q + "38" + Q + "></p>");
			}
			sw1.WriteLine("<h1 align=" + Q + "center" + Q + "><font color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">Chronology Of Events</font></h1>");
			sw1.WriteLine("<hr>");

			for ( iCnt = 0 ; iCnt <= iNumItems - 1; iCnt++)
			{

				if ( iYear != MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].TheYear ) 
				{
					if ( iYear != 0 ) 
					{ //end the previous list
						sw1.WriteLine("</ul>");
					}

					iYear = MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].TheYear;
					if ( iYear < 1000 ) 
					{
						sw1.WriteLine("<H2><FONT color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">AD " + iYear.ToString() + "</FONT></H2>");
					} 
					else 
					{
						sw1.WriteLine("<H2><FONT color=" + Q + "black" + Q + " face=" + Q + "Book Antiqua" + Q + ">" + iYear.ToString() + "</FONT></H2>");
					}
					sw1.WriteLine("<ul>");//start a new list;
				}

				sw1.WriteLine("<li style=" + Q + "color: " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ColorCode + Q + ">");

				if ( MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ActualDate != System.DateTime.FromOADate(0) ) 
				{
					sActualDate = MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].ActualDate.ToString("dd MMM");
					sw1.WriteLine("<b><FONT color=" + Q + "black" + Q + ">" + sActualDate + "</FONT></b>&nbsp;-&nbsp;");
				}

				if ( MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].IsAbout == true ) 
				{
					switch (MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EstimateStyle)
					{
						case 1: goto case 2; 
						case 2: goto case 3; 
						case 3: goto case 6; 
						case 6:
							sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was about this time that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
							break;
						case 4:
							sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was before this date that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
							break;
						case 5:
							sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">It was after this date that " + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
							break;
					}
				} 
				else 
				{
					sw1.WriteLine("<FONT color=" + Q + "black" + Q + ">" + MyTimeLineEntries[(int)sl.GetByIndex(iCnt)].EventDetails + "</FONT>");
				}
				sw1.WriteLine("</li>");
			} // iCnt

			sw1.WriteLine("</ul>");

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + Q + "ind_idx.html" + Q + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + Q + configSettings.FamFilePrefix + "_ind_idx.html" + Q + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + Q + "index.htm" + Q + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + Q + configSettings.FamFilePrefix + "_index.htm" + Q + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" ) sw1.Write("<A href=" + Q + "mailto:" + configSettings.AuthorsEmail + Q + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" ) sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + Q + "http://gatheringleaves.org/uged" + Q + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");

			sw1.Close();
			fs1.Close();

		}


		#endregion

		
		#region Methods for building misc. files
		/// <summary>
		/// Summary of BuildGendexFile.
		/// </summary>
		/// 		
		private void BuildGendexFile() 
		{
			string  sFile;
			int iCnt;
			int iGendexEntrys;
			FileStream fs1;
			StreamWriter sw1;


			sFile = configSettings.HtmlPath + "\\GENDEX.txt";
			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			iGendexEntrys = MyGendices.Count;

			if ( iGendexEntrys > 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iGendexEntrys - 1; iCnt++)
				{
            
					if ( sf.Trim(MyGendices[iCnt].Surname) != "" ) 
					{
						sw1.Write(MyGendices[iCnt].PageUrl + "|");
						sw1.Write(MyGendices[iCnt].Surname + "|");
						sw1.Write(MyGendices[iCnt].Fullname + "|");
						if ( sf.IsDate(MyGendices[iCnt].Birthdate) ) 
						{
							sw1.Write(sf.DateValue(MyGendices[iCnt].Birthdate).ToString("dd MMM yyyy") + "|");
						} 
						else 
						{
							sw1.Write(MyGendices[iCnt].Birthdate + "|");
						}
						sw1.Write(MyGendices[iCnt].BirthPlace + "|");
						if ( sf.IsDate(MyGendices[iCnt].DeathDate) ) 
						{
							sw1.Write(sf.DateValue(MyGendices[iCnt].DeathDate).ToString("dd MMM yyyy") + "|");
						} 
						else 
						{
							sw1.Write(MyGendices[iCnt].DeathDate + "|");
						}
						sw1.WriteLine(MyGendices[iCnt].DeathPlace + "|");
					}
				} 
			} // iCnt

			sw1.Close();
			fs1.Close();

		}


		/// <summary>
		/// Summary of BuildLocationsReport.
		/// </summary>
		/// 		
		private void BuildLocationsReport() 
		{
			string  sFile;
			//			string  sData;
			int iLocCount;
			int iNumLocs;
			//			string  QUOTE;
			string  sCurrLoc;
			string  sPrevLoc;
			string  sLocation;
			string  sFile2;

			FileStream fs1;
			StreamWriter sw1;

			FileStream fs2;
			StreamWriter sw2;

			GetLocations();

			iNumLocs = MyLocations.Count;

			SortedList  sl = new SortedList(iNumLocs);

			char QUOTE = '"';

			if ( iNumLocs == 0 ) return;


			for ( iLocCount = 0 ; iLocCount <= iNumLocs - 1; iLocCount++)
			{
				sl.Add(MyLocations[iLocCount].LocationName + CreateGUIDKey(), iLocCount);
			} // iLocCount

			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sFile = configSettings.HtmlPath + "\\locations.html";
			} 
			else 
			{
				sFile = configSettings.HtmlPath + "\\" + configSettings.FamFilePrefix + "_locations.html";
			}

			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			sFile2 = Tools.GetPath() + "\\loc_report.txt";

			fs2 = new FileStream(sFile2, FileMode.Create);
			sw2 = new StreamWriter(fs2);

			//file header
			sw1.WriteLine("<HTML>");
			sw1.WriteLine("<HEAD>");
			if (configSettings.UseCSS == true) sw1.WriteLine("<LINK REL = stylesheet TYPE = text/css href=uged.css>");
			sw1.WriteLine("<TITLE>Locations Report</TITLE>");
			sw1.WriteLine("<META NAME=" + QUOTE + " Generator" + QUOTE + " CONTENT=" + QUOTE + " UncleGed Version " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00") + QUOTE + ">");
			sw1.WriteLine("</HEAD>");
			if ( configSettings.UseBackground ) 
			{
				sw1.WriteLine("<body background=" + QUOTE + configSettings.BackgroundFile + QUOTE + " link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<body link=" + QUOTE + "#0000FF" + QUOTE + " vlink=" + QUOTE + "#800080" + QUOTE + " bgproperties=" + QUOTE + "fixed" + QUOTE + " leftmargin=" + QUOTE + "100" + QUOTE + ">");
			}
			sw1.WriteLine("<p><a name=" + QUOTE + "TOP" + QUOTE + ">&nbsp;</a></p>");
			if ( configSettings.UseBanner ) 
			{
				sw1.WriteLine("<p align=" + QUOTE + "center" + QUOTE + "><img src=" + QUOTE + configSettings.BannerFile + QUOTE + " width=" + QUOTE + "224" + QUOTE + " height=" + QUOTE + "38" + QUOTE + "></p>");
			}
			sw1.WriteLine("<h1><p align=" + QUOTE + "center" + QUOTE + ">Locations</p></h1>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sPrevLoc = "#";
			for ( iLocCount = 0 ; iLocCount <= iNumLocs - 1; iLocCount++)
			{
				if ( _didCancel ) goto BUILDLOC_EXIT;
				sLocation = sf.Left((string)sl.GetKey(iLocCount), sf.Len((string)sl.GetKey(iLocCount)) - 36); //strip off GUID;
				if ( sLocation != "" ) 
				{
					sCurrLoc = sLocation;
					if ( sPrevLoc != sCurrLoc ) 
					{
						sw1.WriteLine("</ul>"); //end prev list;
						sw1.Write("<H2>");
						sw1.Write("<A NAME=LOC" + iLocCount.ToString("000") + ">" + sCurrLoc + "</A>");
						sw2.WriteLine(sCurrLoc);
						sw1.WriteLine("</H2>");
						sPrevLoc = sCurrLoc;
						sw1.WriteLine("<ul>");//start a new list;
					}
					sw1.WriteLine("<li>" + MyLocations[(int)sl.GetByIndex(iLocCount)].PersonName + " (" + EventDescription((MyLocations[(int)sl.GetByIndex(iLocCount)].EventType)) + ")</li>");
				}
			} // iLocCount

			sw1.WriteLine("</ul>");//end prev list;

			sw1.WriteLine("<HR NOSHADE SIZE=1>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "ind_idx.html" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_ind_idx.html" + QUOTE + ">");
			}
			sw1.WriteLine("Index");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<EM><CENTER>");
			if ( configSettings.FamFilePrefix == "fam" ) 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + "index.htm" + QUOTE + ">");
			} 
			else 
			{
				sw1.WriteLine("<A HREF=" + QUOTE + configSettings.FamFilePrefix + "_index.htm" + QUOTE + ">");
			}
			sw1.WriteLine("Table Of Contents");
			sw1.WriteLine("</A>");
			sw1.WriteLine("</CENTER></EM>");
			sw1.WriteLine("<HR NOSHADE SIZE=1>");

			if ( configSettings.AddUserCopyright = true && configSettings.AuthorsName != "" ) 
			{
				sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
				sw1.Write("Copyright &copy; " + DateTime.Now.ToString("yyyy") + "&nbsp;");
				if ( configSettings.AuthorsEmail != "" ) sw1.Write("<A href=" + QUOTE + "mailto:" + configSettings.AuthorsEmail + QUOTE + ">");
				sw1.Write(configSettings.AuthorsName);
				if ( configSettings.AuthorsEmail != "" )  sw1.Write("</A>");
				sw1.WriteLine("</CENTER></P></FONT>");
			}

			sw1.WriteLine("<FONT SIZE=2><P><CENTER>");
			sw1.WriteLine("This page was created on " + DateTime.Now.ToString("MM/dd/yy") + " using <a href=" + QUOTE + "http://gatheringleaves.org/uged" + QUOTE + " target=_blank>UncleGed</a>  ver. " + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMajorPart + "." + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileMinorPart.ToString("00"));
			sw1.WriteLine("Copyright &copy; 2003 D. M. DeBacker");
			sw1.WriteLine("</CENTER></P></FONT>");
			sw1.WriteLine("</BODY>");
			sw1.WriteLine("</HTML>");
			BUILDLOC_EXIT:
				sw1.Close();
			fs1.Close();

			sw2.Close();
			fs2.Close();

		}

		
		/// <summary>
		/// Called by BuildLocationsReport to create as master list of all locations
		/// </summary>
		/// 		
		private void GetLocations() 
		{
			//added in 3.01
			int iCnt;
			int jCnt;
			int iTotItems;
			string  sEventDetails;
			string  sLocation;
			string  sHusband;
			string  sWife;
			string  sName;
			int iNumEvents;
			string  sTemp;
			int iPageNum;
			string  sLinkPage;	
			char Q = '"';

			//wipe everything out
			MyLocations = new Locations();

			//marriages
			iTotItems = MyFamilies.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					//MainForm.pbFile.value = (iCnt / iTotItems) * 100
					sLocation = sf.Trim(MyFamilies[iCnt].MarriagePlace);

					if ( sf.Trim(sLocation) == "" ) continue;

					if ( sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<" ) 
					{
						switch ( configSettings.LocEstimateMethod)
						{
							case 0: //do not list;
								continue;
							case 1://treat same;
								sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
								break;
							case 2://list at end;
								//nothing to do then
								break;
						}
					}

					if ( configSettings.LocReverseOrder ) 
					{
						sLocation = ReverseLocation(sLocation);
					}

					if ( MyFamilies[iCnt].Husband != "?" ) 
					{
						sHusband = MyIndividuals[MyFamilies[iCnt].Husband].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Husband].Surname;
						if ( MyIndividuals[MyFamilies[iCnt].Husband].Suffix != "" ) 
						{
							sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iCnt].Husband].Suffix;
						}
					} 
					else 
					{
						sHusband = "?";
					}

					if ( MyFamilies[iCnt].Wife != "?" ) 
					{
						sWife = MyIndividuals[MyFamilies[iCnt].Wife].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Wife].Surname;
						if ( MyIndividuals[MyFamilies[iCnt].Wife].Suffix != "" ) 
						{
							sWife = sWife + ", " + MyIndividuals[MyFamilies[iCnt].Wife].Suffix;
						}
					} 
					else 
					{
						sWife = "?";
					}

					//@F5@ - example family id - then numeric portion equals the page number
					sTemp = sf.Right(MyFamilies[iCnt].ID, sf.Len(MyFamilies[iCnt].ID) - 2);
					iPageNum = System.Convert.ToInt32(sf.Left(sTemp, sf.Len(sTemp) - 1));
					sLinkPage = configSettings.FamFilePrefix + iPageNum.ToString("000") + ".html";

					if ( sHusband != "?" ) 
					{
						if ( configSettings.ChronoLinks == true ) sEventDetails = "<a href=" + Q + sLinkPage + Q + ">";
						sEventDetails = sEventDetails + sHusband;
						if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";
					} 
					else 
					{
						sEventDetails = sHusband;
					}
					sEventDetails = sEventDetails + " and ";
					if ( sWife != "?" ) 
					{
						if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "<a href=" + Q + sLinkPage + Q + ">";
						sEventDetails = sEventDetails + sWife;
						if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";
					} 
					else 
					{
						sEventDetails = sEventDetails + sWife;
					}
					if ( configSettings.LocDisplayEventDates = true && MyFamilies[iCnt].MarriageDateText != "" ) 
					{
						sEventDetails = sEventDetails + " - " + MyFamilies[iCnt].MarriageDateText;
					}
					if ( MyFamilies[iCnt].MarriagePlace != "" ) 
					{
						MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etMarriage, CreateGUIDKey());
					}
				} // iCnt
			}

			//births
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					//MainForm.pbFile.value = (iCnt / iTotItems) * 100
					sLocation = sf.Trim(MyIndividuals[iCnt].BirthPlace);
					if ( sf.Trim(sLocation) == "" ) continue;

					if ( sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<" ) 
					{
						switch (configSettings.LocEstimateMethod)
						{
							case 0: //do not list;
								continue;
							case 1: //treat same;
								sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
								break;
							case 2: //list at end;
								//nothing to do then
								break;
						}
					}

					if ( configSettings.LocReverseOrder ) 
					{
						sLocation = ReverseLocation(sLocation);
					}

					sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
					if ( MyIndividuals[iCnt].Suffix != "" ) 
					{
						sName = sName + ", " + MyIndividuals[iCnt].Suffix;
					}
					if ( configSettings.ChronoLinks == true ) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
					sEventDetails = sEventDetails + sName;
					if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";
					if ( configSettings.LocDisplayEventDates = true && MyIndividuals[iCnt].BirthDateText != "" ) 
					{
						sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].BirthDateText;
					}
					if ( MyIndividuals[iCnt].BirthPlace != "" ) 
					{
						MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etBirth, CreateGUIDKey());
					}
				} // iCnt
			}

			//deaths
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					sLocation = sf.Trim(MyIndividuals[iCnt].DeathPlace);
					if ( sf.Trim(sLocation) == "" ) continue;

					if ( sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<" ) 
					{
						switch (configSettings.LocEstimateMethod)
						{
							case 0: //do not list;
								continue;
							case 1: //treat same;
								sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
								break;
							case 2: //list at end;
								//nothing to do then
								break;
						}
					}

					if ( configSettings.LocReverseOrder ) 
					{
						sLocation = ReverseLocation(sLocation);
					}

					sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
					if ( MyIndividuals[iCnt].Suffix != "" ) 
					{
						sName = sName + ", " + MyIndividuals[iCnt].Suffix;
					}

					if ( configSettings.ChronoLinks == true )  sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
					sEventDetails = sEventDetails + sName;
					if ( configSettings.ChronoLinks == true )  sEventDetails = sEventDetails + "</a>";
					if ( configSettings.LocDisplayEventDates = true && MyIndividuals[iCnt].DeathDateText != "" ) 
					{
						sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].DeathDateText;
					}
					if ( MyIndividuals[iCnt].DeathPlace != "" ) 
					{
						MyLocations.Add(sLocation, sEventDetails, LifeEvent.EventTypes.etDeath, CreateGUIDKey());
					}
				} // iCnt
			}

			//life events
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
					if ( iNumEvents != 0 ) 
					{
						for ( jCnt = 0 ; jCnt <= iNumEvents - 1; jCnt++)
						{
							sEventDetails = "";

							if ( MyIndividuals[iCnt].LifeEvents[jCnt].EventType == LifeEvent.EventTypes.etOccupation ) 
							{
								if ( configSettings.IgnoreOccupations == true ) continue;
							}

							sLocation = sf.Trim(MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace);
							if ( sf.Trim(sLocation) == "" ) continue;

							if ( sf.Left(sLocation, 1) == "[" || sf.Left(sLocation, 1) == "<" ) 
							{
								switch (configSettings.LocEstimateMethod)
								{
									case 0: //do not list;
										continue;
									case 1: //treat same;
										sLocation = sf.Mid(sLocation, 2, sf.Len(sLocation) - 2);
										break;
									case 2: //list at end;
										//nothing to do then
										break;
								}
							}

							if ( configSettings.LocReverseOrder ) 
							{
								sLocation = ReverseLocation(sLocation);
							}

							sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
							if ( MyIndividuals[iCnt].Suffix != "" ) 
							{
								sName = sName + ", " + MyIndividuals[iCnt].Suffix;
							}

							if ( configSettings.ChronoLinks == true ) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
							sEventDetails = sEventDetails + sName;
							if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";
							if ( configSettings.LocDisplayEventDates = true && MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString != "" ) 
							{
								sEventDetails = sEventDetails + " - " + MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString;
							}

							if ( MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace != "" ) 
							{
								MyLocations.Add(sLocation, sEventDetails, MyIndividuals[iCnt].LifeEvents[jCnt].EventType, CreateGUIDKey());
							}
						} // jCnt
					}
				} // iCnt
			}

		}


		#endregion

		//HELPER FUNCTIONS

		/// <summary>
		/// Returns a text description of a given event type.
		/// </summary>
		/// <param name=EventType></param>
		/// 		
		private string  EventDescription(LifeEvent.EventTypes EventType) 
		{
			string  eventText = "";

			switch (EventType) 
			{
				case LifeEvent.EventTypes.etUnknown : eventText = "Unknown event"; break;
				case LifeEvent.EventTypes.etDeathOfSpouse : eventText = "Death Of Spouse"; break;
				case LifeEvent.EventTypes.etBirth : eventText = "Birth"; break;
				case LifeEvent.EventTypes.etDeath : eventText = "Death"; break;
				case LifeEvent.EventTypes.etBurial : eventText = "Burial"; break;
				case LifeEvent.EventTypes.etOccupation : eventText = "Occupation"; break;
				case LifeEvent.EventTypes.etMarriage : eventText = "Marriage"; break;
				case LifeEvent.EventTypes.etResidence : eventText = "Residence"; break;
				case LifeEvent.EventTypes.etDivorce : eventText = "Divorce"; break;
				case LifeEvent.EventTypes.etImmigration : eventText = "Immigration"; break;
				case LifeEvent.EventTypes.etMilitary : eventText = "Military"; break;
				case LifeEvent.EventTypes.etOther : eventText = "Other"; break;
				case LifeEvent.EventTypes.etElected : eventText = "Elected"; break;
				case LifeEvent.EventTypes.etExcommunicated : eventText = "Excommunicated"; break;
				case LifeEvent.EventTypes.etMission : eventText = "Mission"; break;
				case LifeEvent.EventTypes.etBaptismLDS : eventText = "Baptism LDS"; break;
				case LifeEvent.EventTypes.etBaptism : eventText = "Baptism"; break;
				case LifeEvent.EventTypes.etBar_Mitzvah : eventText = "Bar Mitzvah"; break;
				case LifeEvent.EventTypes.etBat_Mitzvah : eventText = "Bat Mitzah"; break;
				case LifeEvent.EventTypes.etBlessing : eventText = "Blessing"; break;
				case LifeEvent.EventTypes.etCaste : eventText = "Caste"; break;
				case LifeEvent.EventTypes.etCensus : eventText = "Census"; break;
				case LifeEvent.EventTypes.etChristening : eventText = "Christening"; break;
				case LifeEvent.EventTypes.etConfirmation : eventText = "Confirmation"; break;
				case LifeEvent.EventTypes.etConfirmationLDS : eventText = "Confirmation LDS"; break;
				case LifeEvent.EventTypes.etCremation : eventText = "Cremation"; break;
				case LifeEvent.EventTypes.etEducation : eventText = "Education"; break;
				case LifeEvent.EventTypes.etEmigration : eventText = "Emigration"; break;
				case LifeEvent.EventTypes.etEndowmentLDS : eventText = "Endowment LDS"; break;
				case LifeEvent.EventTypes.etFirstCommunion : eventText = "First Communion"; break;
				case LifeEvent.EventTypes.etGraduation : eventText = "Graduation"; break;
				case LifeEvent.EventTypes.etNaturalization : eventText = "Naturalization"; break;
				case LifeEvent.EventTypes.etOrdination : eventText = "Ordination"; break;
				case LifeEvent.EventTypes.etProbate : eventText = "Probate"; break;
				case LifeEvent.EventTypes.etProperty : eventText = "Property"; break; 
				case LifeEvent.EventTypes.etReligion : eventText = "Religion"; break;
				case LifeEvent.EventTypes.etRetirement : eventText = "Retirement"; break;
				case LifeEvent.EventTypes.etSealedToParentsLDS : eventText = "Sealed To Parents LDS" ; break; 
				case LifeEvent.EventTypes.etSSN : eventText = "SSN"; break;
				case LifeEvent.EventTypes.etWill : eventText = "Will"; break;
			}

			return eventText;

		}

		
		/// <summary>
		/// Summary of FixDate.
		/// </summary>
		/// <param name=sData></param>
		/// 		
		private string  FixDate(string  sData) 
		{
			//fixes dates with EST, ABT, etc.
			string  sTemp;
			int x;
			//			int iToPoint;
			string  sTemp2 = "";
			bool bHasAnd = false;
			string  sDate;

			sDate = StripChar(sData, ".", true);

			sTemp = sf.Trim(sDate);

			if ( sf.UCase(sf.Left(sTemp, 3)) == "ABT" ) 
			{
				sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				if ( sf.IsDate(sTemp) ) sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");;
				sTemp = "abt. " + sTemp;
			}

			if ( sf.UCase(sf.Left(sTemp, 3)) == "CAL" ) 
			{
				sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				if ( sf.IsDate(sTemp) )  sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
				sTemp = sTemp + " (calc)";
			}

			if ( sf.UCase(sf.Left(sTemp, 3)) == "EST" ) 
			{
				sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				if ( sf.IsDate(sTemp) )  sTemp =  sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
				sTemp = sTemp + " (est)";
			}

			if ( sf.UCase(sf.Left(sTemp, 3)) == "BEF" ) 
			{
				sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				if ( sf.IsDate(sTemp) )  sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
				sTemp = "bef. " + sTemp;
			}

			if ( sf.UCase(sf.Left(sTemp, 3)) == "AFT" ) 
			{
				sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				if ( sf.IsDate(sTemp) )  sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");
				sTemp = "aft. " + sTemp;
			}

			if ( sf.UCase(sf.Left(sTemp, 3)) == "BET" ) 
			{
				x = sf.InStr(sDate, "-");
				if ( x == 0 ) 
				{
					x = sf.InStr(sDate, "AND");
					if ( x != 0 ) 
					{ 
						bHasAnd = true; 
					} 
					else 
					{ 
						bHasAnd = false;
					}
				}
				if ( x > 0 ) 
				{
					sTemp = sf.Trim(sf.Mid(sTemp, 5, x - 5));
				} 
				else 
				{
					sTemp = sf.Trim(sf.Right(sTemp, sf.Len(sTemp) - 3));
				}
				if ( sf.IsDate(sTemp) )  sTemp = sf.DateValue(sTemp).ToString("MMMM dd, yyyy");

				if ( x > 0 && bHasAnd == false ) 
				{
					sTemp2 = sf.Trim(sf.Right(sDate, sf.Len(sDate) - x));
				} 
				else if ( x > 0 && bHasAnd == true ) 
				{
					sTemp2 = sf.Trim(sf.Right(sDate, sf.Len(sDate) - (x + 2)));
				}
				if ( sf.IsDate(sTemp2) ) sTemp2 = sf.DateValue(sTemp2).ToString("MMMM dd, yyyy");

				sTemp = "between " + sTemp;

				if ( x > 0 ) 
				{
					sTemp = sTemp + " and " + sTemp2;
				}

			}

			return sTemp;
		}

		
		/// <summary>
		/// Summary of FixRin.
		/// </summary>
		/// <param name=sRin></param>
		/// 		
		public string  FixRin( string  sRin) 
		{
			string  sTemp;
			sTemp = sf.Trim(sRin);
			sTemp = sf.Right(sTemp, sf.Len(sTemp) - 2);
			sTemp = sf.Left(sTemp, sf.Len(sTemp) - 1);
			return sTemp;
		}

		/// <summary>
		/// if the husband or wife is an empty string change it to a question mark
		/// </summary>
		/// 		
		private void FixFamiliesEach() 
		{
			int iNumFams;

			iNumFams = MyFamilies.Count;

			if ( iNumFams == 0 ) return; 
			foreach (Family family in MyFamilies)
			{
				if ( _didCancel ) return; 
				if ( sf.Trim(family.Husband) == "" ) 
				{
					family.Husband = "?";
				}
				if ( sf.Trim(family.Wife) == "" ) 
				{
					family.Wife = "?";
				}
			} // family //iFamCount

		}

		
		/// <summary>
		/// Summary of MarkAsPrivate.
		/// </summary>
		/// 		
		private void MarkAsPrivate() 
		{
			DateTime ActualDate;
			DateTime CutOffDate;

			CutOffDate = new DateTime(DateTime.Now.Year - 80, DateTime.Now.Month, DateTime.Now.Day);

			foreach (Individual person in MyIndividuals)
			{
				if ( sf.IsDate(person.BirthDateText) && (sf.Trim(person.DeathDateText) == "") ) 
				{
					ActualDate = sf.DateValue(person.BirthDateText);
					if ( ActualDate > CutOffDate ) 
					{
						person.BirthDateText = Privacy;
					}
				}
			} // person

		}


		/// <summary>
		/// Summary of SecondsToHMS.
		/// </summary>
		/// <param name=lSeconds></param>
		/// 		
		private string  SecondsToHMS(int lSeconds) 
		{
			string  sHour;
			string  sMinute;
			string  sSecond;
			int iHour;
			int iMinute;
			int iSecond;
			int lRemain;

			if ( lSeconds >= 3600 ) 
			{
				iHour = (int)(lSeconds / 60 / 60);
				lRemain = lSeconds - ((int)(iHour) * 60 * 60);
			} 
			else 
			{
				iHour = 0;
				lRemain = lSeconds;
			}

			sHour = iHour.ToString("00");

			if ( lSeconds >= 60 ) 
			{
				iMinute = (int)(lRemain / 60);
				lRemain = lSeconds - (((int)(iHour) * 60 * 60) + ((int)(iMinute) * 60));
			} 
			else 
			{
				iMinute = 0;
				lRemain = lSeconds;
			}

			sMinute = iMinute.ToString("00");

			iSecond = lRemain;
			sSecond = iSecond.ToString("00");

			return (sHour + ":" + sMinute + ":" + sSecond);
		}

		
		/// <summary>
		/// Summary of GetSoundexCode.
		/// </summary>
		/// <param name=sSurname></param>
		/// 		
		private string  GetSoundexCode(string  sSurname) 
		{

			//1 - B,P,F,V
			//2 - C,S,G,J,K,Q,X,Z
			//3 - D,T
			//4 - L
			//5 - M,N
			//6 - R
			//
			//The letters A,E,I,O,U,Y,H, and W are not coded.
			//Names with adjacent letters having the same equivalent number are coded as one letter with a single number.
			//Surname prefixes are generally not used in the soundex.

			string  sSoundex;
			string  sTemp;
			int iCnt;
			int iIndx;
			string  sChar;
			string  sPrevChar;

			if ( sSurname == "" ) 
			{
				return "";
			}

			sSurname = sf.Trim(sf.UCase(sSurname));

			if ( sf.Left(sSurname, 2) == "KN" ) 
			{ //special case for names that begin w/ KN
				sSoundex = "N";
				sTemp = sf.Right(sSurname, sf.Len(sSurname) - 2);
			} 
			else 
			{
				sSoundex = sf.Left(sSurname, 1);
				sTemp = sf.Right(sSurname, sf.Len(sSurname) - 1);
			}

			iIndx = 0;

			for ( iCnt = 1 ; iCnt <= sf.Len(sTemp); iCnt++)
			{

				sChar = sf.Mid(sTemp, iCnt, 1);

				//if ( sChar != sPrevChar ) {
				switch (sChar)
				{
					case "B": 
					case "P": 
					case "F": 
					case "V":
						if ( sf.Right(sSoundex, 1) != "1" ) 
						{
							sSoundex = sSoundex + "1";
							iIndx = iIndx + 1;
						}
						break;
					case "C":
					case "S":
					case "G":
					case "J":
					case "K":
					case "Q":
					case "X":
					case "Z":
						if ( sf.Right(sSoundex, 1) != "2" ) 
						{
							sSoundex = sSoundex + "2";
							iIndx = iIndx + 1;
						}
						break;
					case "D":
					case "T":
						if ( sf.Right(sSoundex, 1) != "3" ) 
						{
							sSoundex = sSoundex + "3";
							iIndx = iIndx + 1;
						}
						break;
					case "L":
						if ( sf.Right(sSoundex, 1) != "4" ) 
						{
							sSoundex = sSoundex + "4";
							iIndx = iIndx + 1;
						}
						break;
					case "M":
					case "N":
						if ( sf.Right(sSoundex, 1) != "5" ) 
						{
							sSoundex = sSoundex + "5";
							iIndx = iIndx + 1;
						}
						break;
					case "R":
						if ( sf.Right(sSoundex, 1) != "6" ) 
						{
							sSoundex = sSoundex + "6";
							iIndx = iIndx + 1;
						}
						break;
				}
				//}

				sPrevChar = sChar;
				if ( iIndx == 3 )  break; //fixed in 2.1 was set to 4
			} // iCnt

			//pad with zeros
			if ( sf.Len(sSoundex) == 1 )  sSoundex = sSoundex + "000";
			if ( sf.Len(sSoundex) == 2 ) sSoundex = sSoundex + "00";
			if ( sf.Len(sSoundex) == 3 ) sSoundex = sSoundex + "0";

			return sSoundex;

		}

		
		/// <summary>
		/// Summary of LongDirFix.
		/// </summary>
		/// <param name=sIncomming></param>
		/// <param name=iMax></param>
		/// 		
		private string  LongDirFix(string  sIncomming, int iMax) 
		{
			int I;
			int LblLen;
			//			int StringLen;
			string  TempString;

			TempString = sIncomming;
			LblLen = iMax;
			if ( sf.Len(TempString) <= LblLen ) 
			{
				return TempString;
			}
			LblLen = LblLen - 6;
			for ( I = sf.Len(TempString) - LblLen ; I <= sf.Len(TempString); I++)
			{
				if ( sf.Mid(TempString, I, 1) == "\\" ) break;
			} //
			return sf.Left(TempString, 3) + "..." + sf.Right(TempString, sf.Len(TempString) - (I - 1));
		}

		
		/// <summary>
		/// Summary of FindIndividual.
		/// </summary>
		/// <param name=iIndex></param>
		/// 		
		private void FindIndividual(int iIndex) 
		{

			//			Family MyFamily;
			//			Child MyChild;
			string  TheFamID;

			DateTime ActualDate;

			int iGedFileIndex;
			string  sSoundex;
			string  sSurname;
			string  sGivenName;
			string  sSex;
			string  sBirthPlace;
			string  sBirthDateText;
			object datBirthDate;
			string  sDeathPlace;
			string  sDeathDateText;
			object datDeathDate;
			string  sFather;
			string  sMother;
			string  sSpouse;
			string  sMarriagePlace;
			string  sMarriageDateText;
			object datMarriageDate;

      
			iGedFileIndex = 0;
			sSoundex = "";
			sSurname = "";
			sGivenName = "";
			sSex = "";
			sBirthPlace = "";
			sBirthDateText = "";
			datBirthDate = "";
			sDeathPlace = "";
			sDeathDateText = "";
			datDeathDate = "";
			sFather = "";
			sMother = "";
			sSpouse = "";
			sMarriagePlace = "";
			sMarriageDateText = "";
			datMarriageDate = "";


			//sFileName = sFile
			iGedFileIndex = iIndex;
			sSurname = sf.UCase(MyIndividuals[iIndex].Surname);
			sSoundex = GetSoundexCode((MyIndividuals[iIndex].Surname));
			sGivenName = MyIndividuals[iIndex].Forenames;
			if ( MyIndividuals[iIndex].Suffix != "" ) 
			{
				sGivenName = sGivenName + "," + MyIndividuals[iIndex].Suffix;
			}
			sGivenName = sGivenName;
			sSex = MyIndividuals[iIndex].Sex;

			//birth info
			if ( MyIndividuals[iIndex].BirthDateText != "" && MyIndividuals[iIndex].BirthDateText != Privacy ) 
			{
				sBirthDateText = MyIndividuals[iIndex].BirthDateText;
				sBirthPlace = MyIndividuals[iIndex].BirthPlace;
				ActualDate = sf.DateValue(MyIndividuals[iIndex].BirthDateText);
				if ( ActualDate.Year != 1 ) 
				{
					datBirthDate = ActualDate.Year;
					ActualDate = new DateTime();
				}
			} 
			else if ( MyIndividuals[iIndex].BirthDateText == Privacy ) 
			{
				sBirthDateText = Privacy;
			}

			//death info
			if ( MyIndividuals[iIndex].DeathDateText != "" && MyIndividuals[iIndex].DeathDateText != Privacy ) 
			{
				sDeathDateText = MyIndividuals[iIndex].DeathDateText;
				sDeathPlace = MyIndividuals[iIndex].DeathPlace;
				ActualDate = sf.DateValue(MyIndividuals[iIndex].DeathDateText);
				if ( ActualDate.Year != 1 ) 
				{
					datDeathDate = ActualDate.Year;
					ActualDate = new DateTime();
				}
			} 
			else if ( MyIndividuals[iIndex].DeathDateText == Privacy ) 
			{
				sDeathDateText = Privacy;
			}

			//get spouse and marriage information
			switch (MyIndividuals[iIndex].Sex) 
			{
				case "M":
					foreach (Family family in MyFamilies)
					{
						if ( MyIndividuals[iIndex].ID == family.Husband ) 
						{
							sSpouse = "";
							if ( family.Wife != "?" ) 
							{
								sSpouse = MyIndividuals[family.Wife].Forenames;
								sSpouse = sSpouse + " " + sf.UCase(MyIndividuals[family.Wife].Surname);
								if ( MyIndividuals[family.Wife].Suffix != "" ) 
								{
									sSpouse = sSpouse + ", " + MyIndividuals[family.Wife].Suffix;
								}
							}
							sSpouse = sSpouse;

							if ( family.MarriageDateText != Privacy ) 
							{
								sMarriagePlace = family.MarriagePlace;
								sMarriageDateText = family.MarriageDateText;
								ActualDate = sf.DateValue(family.MarriageDateText);
								if ( ActualDate.Year != 1 ) 
								{
									datMarriageDate = ActualDate.Year;
									ActualDate = new DateTime();
								}
							} 
							else 
							{
								sMarriageDateText = Privacy;
							}
							break;
						}
					} // family
					break;
				case "F":
					foreach (Family family in MyFamilies)
					{
						if ( MyIndividuals[iIndex].ID == family.Wife ) 
						{
							sSpouse = "";
							if ( family.Husband != "?" ) 
							{
								sSpouse = MyIndividuals[family.Husband].Forenames;
								sSpouse = sSpouse + " " + sf.UCase(MyIndividuals[family.Husband].Surname);
								if ( MyIndividuals[family.Husband].Suffix != "" ) 
								{
									sSpouse = sSpouse + ", " + MyIndividuals[family.Husband].Suffix;
								}
							}
							sSpouse = sSpouse;
							if ( family.MarriageDateText != Privacy ) 
							{
								sMarriagePlace = family.MarriagePlace;
								sMarriageDateText = family.MarriageDateText;
								ActualDate = sf.DateValue(family.MarriageDateText);
								if ( ActualDate.Year != 1 ) 
								{
									datMarriageDate = ActualDate.Year;
									ActualDate = new DateTime();
								}
							} 
							else 
							{
								sMarriageDateText = Privacy;
							}
							break;
						}
					} // MyFamily
					break;
			}
			//================
			//get info on parents
			TheFamID = FindIndFamily((MyIndividuals[iIndex].ID));
			if ( TheFamID != "" ) 
			{
				//he is in this family
				if ( MyFamilies[TheFamID].Husband != "?" ) 
				{
					sFather = MyIndividuals[MyFamilies[TheFamID].Husband].Forenames + " " + MyIndividuals[MyFamilies[TheFamID].Husband].Surname;
					sFather = sf.Trim(sFather);
				}
				if ( MyFamilies[TheFamID].Wife != "?" ) 
				{
					sMother = MyIndividuals[MyFamilies[TheFamID].Wife].Forenames + " " + MyIndividuals[MyFamilies[TheFamID].Wife].Surname;
					sMother = sf.Trim(sMother);
				}
			}

		}

		
		/// <summary>
		/// Summary of FindIndFamily.
		/// </summary>
		/// <param name=sIndID></param>
		/// 		
		private string  FindIndFamily(string  sIndID) 
		{
			//use a binary search to find the child family id for this individual
			//returns the child//s family id
			int MinIndex;
			int MaxIndex;
			string  sSearch;
			int iFound;

			MinIndex = 1;
			MaxIndex = MyChildren.Count;
			sSearch = sIndID;

			iFound = BSearchChildren(MinIndex, MaxIndex, sSearch);

			if ( iFound > 0 ) 
			{
				return MyChildren[iFound].FamilyID;
			} 
			else 
			{
				return "";
			}

		}

		
		/// <summary>
		/// Summary of BSearchChildren.
		/// </summary>
		/// <param name=First></param>
		/// <param name=Last></param>
		/// <param name=Value></param>
		/// 		
		private int BSearchChildren(int First, int Last, string Value) 
		{
			//perform a recursive binary search for the child//s family id
			int MidList;

			//is the middle one the one we are looking for?
			MidList = (int)((First + Last) / 2);
			if ( MyChildren[MidList].ChildID == Value ) 
			{
				return MidList;
			}

			//check the first
			if ( MyChildren[First].ChildID == Value ) 
			{
				return  First;
			}

			//and the last
			if ( MyChildren[Last].ChildID == Value ) 
			{
				return  Last;
			}

			//if there is only one left in the list then exit
			if ( MidList == First || MidList == Last ) 
			{
				return -1;
			}

			//half the list according to the Value//s position
			if ( System.Convert.ToInt32(Value) < System.Convert.ToInt32(MyChildren[MidList].ChildID) ) 
			{
				Last = MidList;
			} 
			else 
			{
				First = MidList + 1;
			}

			return BSearchChildren(First, Last, Value);

		}

		
		/// <summary>
		/// Summary of SetChildrenFlag.
		/// </summary>
		/// 		
		private void SetChildrenFlag() 
		{
			int iNumFams;
			int iFamCount;
			string  FamRefID;

			iNumFams = MyFamilies.Count;
			for ( iFamCount = 0 ; iFamCount <= iNumFams - 1; iFamCount++)
			{
				if ( _didCancel ) return;
				FamRefID = MyFamilies[iFamCount].ID;
				foreach (Child child in MyChildren)
				{
					if ( _didCancel ) return;
					if ( child.FamilyID == FamRefID ) 
					{
						MyFamilies[iFamCount].HasChildren = true;
						break;
					}
				}	 // child
			} // iFamCount
			return;
		}

		
		/// <summary>
		/// Summary of SetOwnFamilyFlag.
		/// </summary>
		/// 		
		private void SetOwnFamilyFlag() 
		{

			int iChildCnt =  0;
			int iNumChildren;

			iNumChildren = MyChildren.Count;


			foreach (Child child in MyChildren)
			{
				if ( _didCancel ) return;
				iChildCnt = iChildCnt + 1;

				foreach (Family family in MyFamilies)
				{
					if ( _didCancel ) return;
					if ( MyIndividuals[child.ChildID].Sex == "M" ) 
					{
						if ( child.ChildID == family.Husband ) 
						{
							MyIndividuals[child.ChildID].HasOwnFamily = true;
							break;
						}
					} 
					else 
					{
						if ( child.ChildID == family.Wife ) 
						{
							MyIndividuals[child.ChildID].HasOwnFamily = true;
							break;
						}
					}
				} // family
			} // child

			return;
		}

		
		/// <summary>
		/// Summary of GetFilePart.
		/// </summary>
		/// <param name=sFullPath></param>
		/// <param name=iOption></param>
		/// 		
		private string  GetFilePart( string  sFullPath, short iOption) 
		{
			string  sDriveLetter;
			string  sDirPath;
			string  sFileName;
			string  sExtension;
			int iPathLength;
			int iOffset;
			int iThisLength;
			bool bFileNameFound = false;

			sDriveLetter = "";
			sDirPath = "";
			sFileName = "";
			sExtension = "";

			if ( sf.Mid(sFullPath, 2, 1) == ":" ) 
			{ // Find the drive letter.
				sDriveLetter = sf.Left(sFullPath, 2);
				sFullPath = sf.Mid(sFullPath, 3);
			}
			iPathLength = sf.Len(sFullPath);
			for ( iOffset = iPathLength ; iOffset <= 1; iOffset--)
			{ // Find the next delimiter.
				switch (sf.Mid(sFullPath, iOffset, 1))
				{
					case ".":// This indicates either an extension or a . or a ..;
						iThisLength = sf.Len(sFullPath) - iOffset;
						if ( iThisLength >= 1 && iThisLength <= 3 ) 
						{ // sExtension
							sExtension = sf.Mid(sFullPath, iOffset, iThisLength + 1);
						}
						sFullPath = sf.Left(sFullPath, iOffset - 1);
						break;
					case "\\": // This indicates a path delimiter.;
						iThisLength = sf.Len(sFullPath) - iOffset;
						if ( iThisLength >= 1 && iThisLength <= 8 ) 
						{ // Filename
							sFileName = sf.Mid(sFullPath, iOffset + 1, iThisLength);
							sFullPath = sf.Left(sFullPath, iOffset);
							bFileNameFound = true;
							break;
						}
						break;
					default:
						break;
				}
			} // iOffset

			if ( bFileNameFound == false ) 
			{
				sFileName = sFullPath;
			} 
			else 
			{
				sDirPath = sFullPath;
			} // Print to form for display.

			switch (iOption)
			{
				case GET_DRIVE:
					return sDriveLetter;
				case GET_DIRECTORY:
					return sDirPath;
				case GET_FILENAME:
					return sFileName;
				case GET_EXTENSION:
					return sExtension;
				default:
					return "";
			}

		}

		
		/// <summary>
		/// Summary of FixEstLoc.
		/// </summary>
		/// <param name=sLocation></param>
		/// 		
		private string  FixEstLoc(string  sLocation) 
		{
			//strips off "< >" from an estimated location - see Legacy 3.0

			try
			{

				string  sTemp;


				sTemp = sf.Trim(sLocation);

				if ( sf.Left(sTemp, 1) == "<" && sf.Right(sTemp, 1) == ">" ) 
				{
					sTemp = sf.Right(sTemp, sf.Len(sTemp) - 1);
					sTemp = sf.Left(sTemp, sf.Len(sTemp) - 1);
					sTemp = "&lt;" + sTemp + "&gt;";
				}

				return sTemp;
			} 
			catch 
			{

				return sLocation;
			}
		}

		/// <summary>
		/// Summary of GetTimeLineEvents.
		/// </summary>
		/// 		
		private void GetTimeLineEvents() 
		{
			//added in 3.01
			int iCnt;
			int jCnt;
			DateTime dtActualDate = new DateTime();
			int iYear = 0;
			int iTotItems;
			string  sDateText;
			string  sEventDetails;
			string  sHusband;
			string  sWife;
			string  sName;
			int iNumEvents;
			string  sEventText;
			bool bIsAbout = false;
			int iEstimateStyle = 0;
			string  sColorCode;
			//string  Q;
			string  sLinkPage;
			string  sTemp;
			int iPageNum;

			char Q = '"';

			//marriages
			iTotItems = MyFamilies.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					//MainForm.pbFile.value = (iCnt / iTotItems) * 100
					sDateText = MyFamilies[iCnt].MarriageDateText;
					Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

					if ( iYear <= configSettings.ChronoCutOff && iYear != 0 ) 
					{
						if ( MyFamilies[iCnt].Husband != "?" ) 
						{
							sHusband = MyIndividuals[MyFamilies[iCnt].Husband].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Husband].Surname;
							if ( MyIndividuals[MyFamilies[iCnt].Husband].Suffix != "" ) 
							{
								sHusband = sHusband + ", " + MyIndividuals[MyFamilies[iCnt].Husband].Suffix;
							}
						} 
						else 
						{
							sHusband = "?";
						}

						if ( MyFamilies[iCnt].Wife != "?" ) 
						{
							sWife = MyIndividuals[MyFamilies[iCnt].Wife].Forenames + " " + MyIndividuals[MyFamilies[iCnt].Wife].Surname;
							if ( MyIndividuals[MyFamilies[iCnt].Wife].Suffix != "" ) 
							{
								sWife = sWife + ", " + MyIndividuals[MyFamilies[iCnt].Wife].Suffix;
							}
						} 
						else 
						{
							sWife = "?";
						}

						//@F5@ - example family id - then numeric portion equals the page number
						sTemp = sf.Right(MyFamilies[iCnt].ID, sf.Len(MyFamilies[iCnt].ID) - 2);
						iPageNum = System.Convert.ToInt32(sf.Left(sTemp, sf.Len(sTemp) - 1));
						sLinkPage = configSettings.FamFilePrefix + iPageNum.ToString("000") + ".html";

						if ( sHusband != "?" ) 
						{
							if ( configSettings.ChronoLinks == true )  sEventDetails = "<a href=" + Q + sLinkPage + Q + ">";
							sEventDetails = sEventDetails + sHusband;
							if ( configSettings.ChronoLinks == true )  sEventDetails = sEventDetails + "</a>";
						} 
						else 
						{
							sEventDetails = sHusband;
						}
						sEventDetails = sEventDetails + " and ";
						if ( sWife != "?" ) 
						{
							if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "<a href=" + Q + sLinkPage + Q + ">";
							sEventDetails = sEventDetails + sWife;
							if ( configSettings.ChronoLinks == true )  sEventDetails = sEventDetails + "</a>";
						} 
						else 
						{
							sEventDetails = sEventDetails + sWife;
						}
						sEventDetails = sEventDetails + " are married";

						if ( MyFamilies[iCnt].MarriagePlace != "" ) 
						{
							sEventDetails = sEventDetails + " in " + MyFamilies[iCnt].MarriagePlace;
						} 
						else 
						{
							sEventDetails = sEventDetails + ".";
						}
						if ( iYear != 0 && (sHusband != "?" || sWife != "?") ) 
						{
							sColorCode = "Pink";
							MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "M" + MyFamilies[iCnt].ID);
						}
					}
				} // iCnt
			}

			//births
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					sDateText = MyIndividuals[iCnt].BirthDateText;
					Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

					if ( iYear <= configSettings.ChronoCutOff && iYear != 0 ) 
					{
						sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
						if ( MyIndividuals[iCnt].Suffix != "" ) 
						{
							sName = sName + ", " + MyIndividuals[iCnt].Suffix;
						}
						if ( configSettings.ChronoLinks == true )  sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
						sEventDetails = sEventDetails + sName;
						if ( configSettings.ChronoLinks == true )  sEventDetails = sEventDetails + "</a>";
						sEventDetails = sEventDetails + " is born";
						if ( MyIndividuals[iCnt].BirthPlace != "" ) 
						{
							sEventDetails = sEventDetails + " in " + MyIndividuals[iCnt].BirthPlace;
						} 
						else 
						{
							sEventDetails = sEventDetails + ".";
						}
						if ( iYear != 0 && MyIndividuals[iCnt].Surname != "" ) 
						{
							sColorCode = "Green";
							MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "B" + MyIndividuals[iCnt].ID);
						}
					}
				} // iCnt
			}

			//deaths
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					sEventDetails = "";
					sDateText = MyIndividuals[iCnt].DeathDateText;
					Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

					if ( iYear <= configSettings.ChronoCutOff && iYear != 0 ) 
					{
						sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
						if ( MyIndividuals[iCnt].Suffix != "" ) 
						{
							sName = sName + ", " + MyIndividuals[iCnt].Suffix;
						}

						if ( configSettings.ChronoLinks == true ) sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
						sEventDetails = sEventDetails + sName;
						if ( configSettings.ChronoLinks == true ) sEventDetails = sEventDetails + "</a>";
						sEventDetails = sEventDetails + " dies";
						if ( MyIndividuals[iCnt].DeathPlace != "" ) 
						{
							sEventDetails = sEventDetails + " in " + MyIndividuals[iCnt].DeathPlace;
						} 
						else 
						{
							sEventDetails = sEventDetails + ".";
						}
						if ( iYear != 0 && MyIndividuals[iCnt].Surname != "" ) 
						{
							sColorCode = "Red";
							MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, "D" + MyIndividuals[iCnt].ID);
						}
					}
				} // iCnt
			}

			//life events
			iTotItems = MyIndividuals.Count;
			if ( iTotItems != 0 ) 
			{
				for ( iCnt = 0 ; iCnt <= iTotItems - 1; iCnt++)
				{
					iNumEvents = MyIndividuals[iCnt].LifeEvents.Count;
					if ( iNumEvents != 0 ) 
					{
						for ( jCnt = 0 ; jCnt <= iNumEvents - 1; jCnt++)
						{
							sEventDetails = "";
							sDateText = MyIndividuals[iCnt].LifeEvents[jCnt].EventDateString;
							Tools.GetDates(sDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

							if ( iYear <= configSettings.ChronoCutOff && iYear != 0 ) 
							{
								sName = MyIndividuals[iCnt].Forenames + " " + MyIndividuals[iCnt].Surname;
								if ( MyIndividuals[iCnt].Suffix != "" ) 
								{
									sName = sName + ", " + MyIndividuals[iCnt].Suffix;
								}

								sEventText = MyIndividuals[iCnt].LifeEvents[jCnt].EventText;
								if ( sf.Left(sEventText, 5) == "Note " ) 
								{
									sEventText = sf.Right(sEventText, sf.Len(sEventText) - 5);
								}

								if ( configSettings.ChronoLinks == true )  sEventDetails = "<a href=" + Q + MyIndividuals[iCnt].LinkPage + Q + ">";
								sEventDetails = sEventDetails + sName;
								if ( configSettings.ChronoLinks == true )  sEventDetails = sEventDetails + "</a>";

								sEventDetails = sEventDetails + "&nbsp;-&nbsp;" + sEventText;

								if ( MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace != "" ) 
								{
									sEventDetails = sEventDetails + " (" + MyIndividuals[iCnt].LifeEvents[jCnt].EventPlace + ")";
								} 
								else 
								{
									sEventDetails = sEventDetails + ".";
								}
								if ( iYear != 0 && MyIndividuals[iCnt].Surname != "" ) 
								{
									switch (MyIndividuals[iCnt].LifeEvents[jCnt].EventType)
									{
										case LifeEvent.EventTypes.etBaptism:
											goto case LifeEvent.EventTypes.etChristening;
										case LifeEvent.EventTypes.etChristening:
											sColorCode = "Gold";
											break;
										case LifeEvent.EventTypes.etBurial:
											goto case LifeEvent.EventTypes.etCremation;
										case LifeEvent.EventTypes.etCremation:
											sColorCode = "DARKMAGENTA";
											break;
										default:
											sColorCode = "Blue";
											break;
									}
									MyTimeLineEntries.Add(iYear, dtActualDate, sEventDetails, bIsAbout, sColorCode, iEstimateStyle, MyIndividuals[iCnt].LifeEvents[jCnt].ID);
								}
							}
						} // jCnt
					}
				} // iCnt
			}

		}

		
		/// <summary>
		/// Summary of GetMarriageLink.
		/// </summary>
		/// <param name=sLink1></param>
		/// <param name=sLink2></param>
		/// 		
		private string  GetMarriageLink(string  sLink1, string  sLink2) 
		{
			int Mrin1;
			int Mrin2;
			string  sTemp;
			int iWhereDot;

			sTemp = sf.Right(sLink1, sf.Len(sLink1) - 3);
			iWhereDot = sf.InStr(sTemp, ".");
			if ( iWhereDot != 0 ) 
			{
				sTemp = sf.Left(sTemp, iWhereDot);
				Mrin1 = System.Convert.ToInt32(sTemp);
			} 
			else 
			{
				Mrin1 = 9999;
			}

			sTemp = sf.Right(sLink2, sf.Len(sLink2) - 3);
			iWhereDot = sf.InStr(sTemp, ".");
			if ( iWhereDot != 0 ) 
			{
				sTemp = sf.Left(sTemp, iWhereDot);
				Mrin2 = System.Convert.ToInt32(sTemp);
			} 
			else 
			{
				Mrin2 = 9999;
			}

			if ( Mrin1 < Mrin2 ) 
			{
				return sLink1;
			} 
			else 
			{
				return sLink2;
			}

		}

		
		/// <summary>
		/// Summary of ReverseLocation.
		/// </summary>
		/// <param name=sLocation></param>
		/// 		
		private string  ReverseLocation(string  sLocation) 
		{
			int iCnt;
			string  sTemp = "";
			int iStart;
			bool bIsEstimate;
			string  sThisLocation;
			int X;

			try
			{


				if ( sf.Trim(sLocation) == "" ) 
				{
					return "";
				}

				sThisLocation = sf.Trim(sLocation);

				if ( sf.Left(sThisLocation, 1) == "[" || sf.Left(sThisLocation, 1) == "<" ) 
				{
					sThisLocation = sf.Mid(sThisLocation, 2, sf.Len(sThisLocation) - 2);
					bIsEstimate = true;
				}

				if ( sf.Left(sThisLocation, 1) == "," )  sThisLocation = sf.Right(sThisLocation, sf.Len(sThisLocation) - 1);
				if ( sf.Right(sThisLocation, 1) == "," ) sThisLocation = sf.Left(sThisLocation, sf.Len(sThisLocation) - 1);

				iStart = sf.Len(sThisLocation) + 1;
				for ( iCnt = sf.Len(sThisLocation) ; iCnt <= 1; iCnt--)
				{
					if ( sf.Mid(sThisLocation, iCnt, 1) == "," ) 
					{
						if ( sf.Len(sTemp) != 0 )  sTemp = sTemp + ", ";
						sTemp = sTemp + sf.Trim(sf.Mid(sThisLocation, iCnt + 1, iStart - iCnt - 1));
						iStart = iCnt;
					}
				} // iCnt
				if ( sf.Len(sTemp) != 0 ) 
				{
					X = sf.InStr(sThisLocation, ", ");
					if ( X != 0 ) 
					{
						sTemp = sTemp + ", " + sf.Left(sThisLocation, X - 1);
					} 
					else 
					{
						sTemp = sThisLocation;
					}
				} 
				else 
				{
					sTemp = sThisLocation;
				}
				sTemp = sf.Trim(sTemp);
				if ( bIsEstimate = true && sTemp != "" ) 
				{
					sTemp = "[" + sTemp + "]";
				}

				return sTemp.Trim();
			}
			catch
			{
				return sLocation;
			}
		}

		
		/// <summary>
		/// Summary of StripChar.
		/// </summary>
		/// <param name=sString></param>
		/// <param name=sChar></param>
		/// <param name=bReplaceWithSpace></param>
		/// 		
		private string  StripChar( string  sString, string  sChar, bool bReplaceWithSpace) 
		{
			string  tempStr1;
			string  tempStr2;

			tempStr1 = sString;
			tempStr1 = sString.Replace(sChar, " ");

			if (! bReplaceWithSpace ) 
			{
				//remove the spaces
				tempStr2 = tempStr1.Replace(" ", "");
				tempStr1 = tempStr2;
			}

			return tempStr1;
		}

		
		/// <summary>
		/// Cleans up the occupation title
		/// </summary>
		/// <param name=sOccupation></param>
		/// 		
		private string  FixOccupation(string  sOccupation) 
		{

			string  sTemp;
			int iCnt;
			string  sTest;

			sOccupation = sf.Trim(sOccupation);
			sTest = "OCCUPATION: ";
			if ( sf.UCase(sf.Left(sOccupation, sf.Len(sTest))) == sTest ) 
			{
				sOccupation = sf.Right(sOccupation, sf.Len(sOccupation) - sf.Len(sTest));
			}

			sTemp = sf.Trim(sOccupation);

			//strip off any articles such as a, an, or the
			if ( sf.UCase(sf.Left(sOccupation, 2)) == "A " ) 
			{
				sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 2);
			}

			if ( sf.UCase(sf.Left(sOccupation, 3)) == "AN " ) 
			{
				sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 3);
			}

			if ( sf.UCase(sf.Left(sOccupation, 4)) == "THE " ) 
			{
				sTemp = sf.Right(sOccupation, sf.Len(sOccupation) - 4);
			}

			//capitalize the first letter of each word in the occupation title
			StringBuilder sb = new StringBuilder(sTemp);

			for ( iCnt = 0 ; iCnt <= sb.Length - 1; iCnt++)
			{
				if ( iCnt == 0 ) 
				{
					sb[0] = System.Convert.ToChar(sb[0].ToString().ToUpper()); 
				} 
				else if ( sb[iCnt - 1] == ' ' ) 
				{
					sb[iCnt] =  System.Convert.ToChar(sb[iCnt].ToString().ToUpper()); 
				}
			} // iCnt

			sTemp = sb.ToString();

			return sTemp;

		}


		/// <summary>
		/// Summary of GetMoreStats.
		/// </summary>
		/// 		
		private MoreStats GetMoreStats() 
		{

			MoreStats moreStats = new MoreStats();
			int NumFamilies = MyFamilies.Count;
			int iFamCnt = 0;
			string  FamRefId = "0" ;
			double childCount = 0;
			Statistics myStatistics;
			DateTime dtActualDate = new DateTime();
			DateTime emptyDate = new DateTime();
			int iYear = 0;
			bool bIsAbout = false;
			int iEstimateStyle = 0;
			int monthNumber;
			int yearNumber;
			int birthYear;
			int deathYear;

			myStatistics = new Statistics();
			for ( iFamCnt = 0 ; iFamCnt <= NumFamilies - 1; iFamCnt++)
			{

				FamRefId = MyFamilies[iFamCnt].ID;
				foreach (Child child in MyChildren)
				{
					if ( child.FamilyID == FamRefId ) 
					{
						childCount += 1;
					}
				} //
				myStatistics.Add(childCount);
			} //
			moreStats.AvgNumChildrenPerFamily = myStatistics.Mean;


			myStatistics = new Statistics();
			foreach (Individual individual in MyIndividuals)
			{
				birthYear = 0;
				deathYear = 0;
				if ( individual.BirthDateText.Length != 0 ) 
				{
					Tools.GetDates(individual.BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
					birthYear = iYear;

					if ( dtActualDate != emptyDate ) 
					{
						monthNumber = dtActualDate.Month;
						switch (monthNumber)
						{
							case 1 : moreStats.NumBornInJAN += 1; break;
							case 2 : moreStats.NumBornInFEB += 1; break;
							case 3 : moreStats.NumBornInMAR += 1; break;
							case 4 : moreStats.NumBornInAPR += 1; break;
							case 5 : moreStats.NumBornInMAY += 1; break;
							case 6 : moreStats.NumBornInJUN += 1; break;
							case 7 : moreStats.NumBornInJUL += 1; break;
							case 8 : moreStats.NumBornInAUG += 1; break;
							case 9 : moreStats.NumBornInSEP += 1; break;
							case 10 : moreStats.NumBornInOCT += 1; break;
							case 11 : moreStats.NumBornInNOV += 1; break;
							case 12 : moreStats.NumBornInDEC += 1; break;
						}
					}

					yearNumber = iYear;
					if ( yearNumber != 0 ) 
					{

						if ( yearNumber < 1600 ) 
						{
							moreStats.CountBornBefore1600 += 1;
						} 
						else if ( yearNumber < 1700 ) 
						{
							moreStats.CountBorn17thCentury += 1;
						} 
						else if ( yearNumber < 1800 ) 
						{
							moreStats.CountBorn18thCentury += 1;
						} 
						else if ( yearNumber < 1900 ) 
						{
							moreStats.CountBorn19thCentury += 1;
						} 
						else if ( yearNumber < 2000 ) 
						{
							moreStats.CountBorn20thCentury += 1;
						}
					}

				}

				if ( individual.DeathDateText.Length != 0 ) 
				{
					Tools.GetDates(individual.DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
					deathYear = iYear;
					if ( dtActualDate != emptyDate ) 
					{
						monthNumber = dtActualDate.Month;
						switch (monthNumber)
						{
							case 1 : moreStats.NumDiedInJAN += 1; break;
							case 2 : moreStats.NumDiedInFEB += 1; break;
							case 3 : moreStats.NumDiedInMAR += 1; break;
							case 4 : moreStats.NumDiedInAPR += 1; break;
							case 5 : moreStats.NumDiedInMAY += 1; break;
							case 6 : moreStats.NumDiedInJUN += 1; break;
							case 7 : moreStats.NumDiedInJUL += 1; break;
							case 8 : moreStats.NumDiedInAUG += 1; break;
							case 9 : moreStats.NumDiedInSEP += 1; break;
							case 10 : moreStats.NumDiedInOCT += 1; break;
							case 11 : moreStats.NumDiedInNOV += 1; break;
							case 12 : moreStats.NumDiedInDEC += 1; break;
						}
					}
				}

				if ( birthYear != 0 && deathYear != 0 ) 
				{
					myStatistics.Add((double)deathYear - birthYear);
				}
			} //

			moreStats.AvgAgeAtDeath = myStatistics.Mean;

			return moreStats;
		}

		
		/// <summary>
		/// Summary of CreateGUIDKey.
		/// </summary>
		/// 		
		private string  CreateGUIDKey() 
		{
			Guid myGUID = Guid.NewGuid();
			return myGUID.ToString();
		}


		/// <summary>
		/// Summary of GetOtherLink.
		/// </summary>
		/// <param name=sThisLink></param>
		/// <param name=iCnt></param>
		/// <param name=bIsBook></param>
		/// 		
		private string GetOtherLink(string  sThisLink, int iCnt, bool bIsBook ) 
		{
			string  sTemp;
			string  sOtherLink;
			string  sChHusband;
			string  sChWife;
			string  sChTitle;

			char QUOTE = '"';

			if ( iCnt == 0 ) 
			{
				sTemp = "See ";
			} 
			else 
			{
				sTemp = " OR ";
			}

			sOtherLink = sThisLink;
			sOtherLink = sf.Right(sOtherLink, sf.Len(sOtherLink) - 2);
			sOtherLink = sf.Left(sOtherLink, sf.Len(sOtherLink) - 1);
			sOtherLink = System.Convert.ToInt32(sOtherLink).ToString("000");
			if ( bIsBook == true ) 
			{
				sOtherLink = "#F-" + sOtherLink;
			} 
			else 
			{
				sOtherLink = configSettings.FamFilePrefix + sOtherLink + ".html";
			}

			sTemp = sTemp + "<A HREF=" + QUOTE + sOtherLink + QUOTE + ">";

			//the husband
			if ( MyFamilies[sThisLink].Husband != "?" ) 
			{
				sChHusband = MyIndividuals[MyFamilies[sThisLink].Husband].Forenames + " " + MyIndividuals[MyFamilies[sThisLink].Husband].Surname;
				if ( MyIndividuals[MyFamilies[sThisLink].Husband].Suffix != "" ) 
				{
					sChHusband = sChHusband + ", " + MyIndividuals[MyFamilies[sThisLink].Husband].Suffix;
				}
			} 
			else 
			{
				sChHusband = "?";
			}

			//the wife
			if ( MyFamilies[sThisLink].Wife != "?" ) 
			{
				sChWife = MyIndividuals[MyFamilies[sThisLink].Wife].Forenames + " " + MyIndividuals[MyFamilies[sThisLink].Wife].Surname;
				if ( MyIndividuals[MyFamilies[sThisLink].Wife].Suffix != "" ) 
				{
					sChWife = sChWife + ", " + MyIndividuals[MyFamilies[sThisLink].Wife].Suffix;
				}
			} 
			else 
			{
				sChWife = "?";
			}

			//title of web page that we are linking to
			sChTitle = sChHusband + " &amp; " + sChWife;

			sTemp = sTemp + sChTitle;
			sTemp = sTemp + "</A>";
			return sTemp;
		}

		
		/// <summary>
		/// Summary of GetOtherMarriages.
		/// </summary>
		/// <param name=sThisIndId></param>
		/// <param name=sThisFamId></param>
		/// 		
		private ArrayList GetOtherMarriages(string  sThisIndId, string  sThisFamId)
		{
			int iNumFound = -1;

			const int MAX_NUM_FOUND = 32; //some ridiculous number

			ArrayList aryOtherFams = new ArrayList(); 

			try 
			{ 
				foreach (Family family in MyFamilies)
				{
					if ( iNumFound == MAX_NUM_FOUND - 1 ) break;
					if ( family.Husband == sThisIndId && family.ID != sThisFamId ) 
					{
						iNumFound++;
						aryOtherFams.Add(family.ID);
					} 
					else if ( family.Wife == sThisIndId && family.ID != sThisFamId ) 
					{
						iNumFound++;
						aryOtherFams.Add(family.ID) ;
					}
				} // family

				
			} 
			catch 
			{
				//empty catch
			}

			return aryOtherFams;

		}

//		public void SaveAsXml()
//		{
//			try
//			{
//
//				System.Xml.Serialization.XmlSerializer  XmlS = new System.Xml.Serialization.XmlSerializer(typeof(gedxml.GEDCOM));
//
//				XmlTextWriter writer = new XmlTextWriter("uged_test.xml", System.Text.Encoding.UTF8);
//				writer.Formatting = Formatting.Indented;
//				XmlS.Serialize(writer, myGedXml);
//				writer.Close();
//
//			} 
//			catch (Exception ex) {
//				Tools.Logit(ex.ToString());
//			}
//		}

		#region Methods For Estimating Dates
		//const for estimating dates
		private const int MAX_LIVING_AGE = 75;
		private const int MAX_BAPT_AGE = 10;
		private const int MAX_BURIAL_ELAPSED = 1;
		private const int MIN_MARR_AGE = 20;
		private const int MIN_CHILDBIRTH = 20;
		private const int MAX_CHILDBIRTH = 50;
		private const int ABT_EQUALS = 2;
		private const int MAX_AGE_DIFF = 10;
		private const int MAX_ITERATIONS = 5;
		private const int MIN_ALLOWED_YEAR = 0;

		public int MinAllowedYear  
		{
			get 
			{
				return MIN_ALLOWED_YEAR;
			}
		}

		/// <summary>
		/// Summary of EstimateBirthDates.
		/// </summary>
		/// 		
		public void EstimateBirthDates() 
		{
			DateTime dtActualDate = new DateTime();
			int iYear =  0;
			bool bIsAbout = false;
			int iEstimateStyle = 0;
			string  sFamKey;
			int iCnt;
			int iLoopCnt;

			Tools.Logit("Performing date estimation.");
			for ( iLoopCnt = 1 ;  iLoopCnt <= MAX_ITERATIONS;  iLoopCnt++)
			{
				Tools.SilentLogit("}: " + iLoopCnt.ToString());
				foreach (Individual individual in MyIndividuals)
				{
					if ( individual.BirthDateText.Length == 0 || individual.DidEstimate == true ) 
					{
						//minBirthYear = 0
						//maxBirthYear = 9999

						Tools.GetDates(individual.BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

						//do we have any dates for this indi?
						Tools.GetDates(individual.BaptismDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
						if ( iYear != 0 ) 
						{
							individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_BAPT_AGE);
							individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
							Tools.SilentLogit("Constraint 1:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
							individual.DidEstimate = true;
						}

						Tools.GetDates(individual.DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
						if ( iYear != 0 ) 
						{
							individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_LIVING_AGE);
							individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
							Tools.SilentLogit("Constraint 2:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
							individual.DidEstimate = true;
						}

						Tools.GetDates(individual.BurialDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
						if ( iYear != 0 ) 
						{
							individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_LIVING_AGE);
							individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
							Tools.SilentLogit("Constraint 3:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
							individual.DidEstimate = true;
						}

						foreach (LifeEvent theLifeEvent in individual.LifeEvents)
						{
							Tools.GetDates(theLifeEvent.EventDateString, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
							if ( iYear != 0 ) 
							{
								if ( iYear < individual.MinBirthYear ) 
								{
									individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear);
									Tools.SilentLogit("Constraint 4:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
									individual.DidEstimate = true;
								}
								if ( iYear > individual.MaxBirthYear ) 
								{
									individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
									Tools.SilentLogit("Constraint 5:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
									individual.DidEstimate = true;
								}
							}
						} //

						//get dates for any spouses
						if ( individual.FamList.Count > 0 ) 
						{
							for ( iCnt = 0 ; iCnt <= individual.FamList.Count - 1; iCnt++)
							{

								//marriage date
								Tools.GetDates(MyFamilies[individual.FamList[iCnt].FamId].MarriageDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
								if ( iYear != 0 ) 
								{
									if ( individual.MinBirthYear > iYear ) 
									{
										individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_MARR_AGE);
										Tools.SilentLogit("Constraint 6:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
										individual.DidEstimate = true;
									}
									if ( individual.MaxBirthYear > iYear ) 
									{
										individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_MARR_AGE);
										Tools.SilentLogit("Constraint 6a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
										individual.DidEstimate = true;
									}
								}

								//the spouses birth date
								iYear = 0;

								if ( individual.Sex == "F" ) 
								{
									if (MyFamilies[individual.FamList[iCnt].FamId].Husband != "?")
									{
										Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Husband].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									}
								} 
								else 
								{
									if (MyFamilies[individual.FamList[iCnt].FamId].Wife != "?")
									{
										Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Wife].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									}
								}
								if ( iYear != 0 ) 
								{
									if ( individual.MinBirthYear > iYear ) 
									{
										individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_MARR_AGE);
										Tools.SilentLogit("Constraint 7:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
										individual.DidEstimate = true;
									}
									if ( individual.MaxBirthYear > iYear ) 
									{
										individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear + MAX_AGE_DIFF);
										individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MAX_AGE_DIFF);
										Tools.SilentLogit("Constraint 8:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
										individual.DidEstimate = true;
									}

									//the spouse//s death date
									if ( individual.Sex == "F" ) 
									{
										Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Husband].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									} 
									else 
									{
										Tools.GetDates(MyIndividuals[MyFamilies[individual.FamList[iCnt].FamId].Wife].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									}
									if ( iYear != 0 ) 
									{
										if ( individual.MaxBirthYear > iYear ) 
										{
											individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_MARR_AGE);
											individual.DidEstimate = true;
											Tools.SilentLogit("Constraint 8a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
										}
									}

								}

								//do the children here....
								//now examine the children//s birth dates
								foreach (Child ch in MyChildren)
								{
									if ( ch.FamilyID == individual.FamList[iCnt].FamId ) 
									{
										Tools.GetDates(MyIndividuals[ch.ChildID].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
										if ( iYear != 0 ) 
										{
											if ( individual.MinBirthYear > iYear ) 
											{
												individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_CHILDBIRTH);
												Tools.SilentLogit("Constraint 14:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
												individual.DidEstimate = true;
											}
											if ( individual.MinBirthYear < iYear - MAX_LIVING_AGE ) 
											{
												individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear - MIN_CHILDBIRTH);
												Tools.SilentLogit("Constraint 14a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
												individual.DidEstimate = true;
											}
											if ( individual.MaxBirthYear > iYear - MIN_MARR_AGE ) 
											{
												individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_CHILDBIRTH);
												Tools.SilentLogit("Constraint 15:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
												individual.DidEstimate = true;
											}
											if ( individual.MaxBirthYear < iYear - MAX_LIVING_AGE ) 
											{
												individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - MIN_CHILDBIRTH);
												Tools.SilentLogit("Constraint 15a:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
												individual.DidEstimate = true;
											}
										}
									}
								} //

							} //
						}

						//get dates for parents
						Child child;
						if (individual.FamilyID.Length != 0)
						{
							sFamKey = individual.FamilyID + individual.ID;
							
							try
							{
								child = MyChildren[sFamKey];
							} 
							catch 
							{
								child = null;
							}
               
							if (child == null) 
							{
								if ( MyFamilies[child.FamilyID].Husband != "?" ) 
								{
									//find dates regarding father
									Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Husband].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									if ( iYear != 0 ) 
									{
										if ( individual.MinBirthYear < iYear ) 
										{
											//adjust based on father//s birth year
											individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear + MIN_MARR_AGE);
											Tools.SilentLogit("Constraint 9:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
											individual.DidEstimate = true;
										}
									}
									Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Husband].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									if ( iYear != 0 ) 
									{
										if ( individual.MaxBirthYear > iYear ) 
										{
											individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear - 1);
											Tools.SilentLogit("Constraint 10:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
											individual.DidEstimate = true;
										}
									}
								}
								if ( MyFamilies[child.FamilyID].Wife != "?" ) 
								{
									//find dates regarding mother
									Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Wife].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									if ( iYear != 0 ) 
									{
										if ( individual.MinBirthYear < iYear ) 
										{
											//adjust based on mother//s birth year
											individual.MinBirthYear = SetMinYear(individual.MinBirthYear, iYear + MIN_CHILDBIRTH);
											Tools.SilentLogit("Constraint 11:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
											individual.DidEstimate = true;
										}
										if ( individual.MaxBirthYear > iYear + MAX_CHILDBIRTH ) 
										{
											//adjust based on mother//s birth year
											individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear + MAX_CHILDBIRTH);
											Tools.SilentLogit("Constraint 12:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
											individual.DidEstimate = true;
										}
									}
									Tools.GetDates(MyIndividuals[MyFamilies[child.FamilyID].Wife].DeathDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);
									if ( iYear != 0 ) 
									{
										if ( individual.MaxBirthYear > iYear ) 
										{
											individual.MaxBirthYear = SetMaxYear(individual.MaxBirthYear, iYear);
											Tools.SilentLogit("Constraint 13:" + iYear.ToString() + ":" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
											individual.DidEstimate = true;
										}
									}
								}
							}						
						} 	
						else 
						{
							child = null;
						}

						if ( individual.MinBirthYear >= MIN_ALLOWED_YEAR ) 
						{
							if ( individual.MinBirthYear > individual.MaxBirthYear ) 
							{
								individual.MaxBirthYear = individual.MinBirthYear;
								Tools.SilentLogit("Min > Max:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
								individual.DidEstimate = true;
							}
							if ( individual.MinBirthYear > DateTime.Now.Year ) 
							{
								individual.MinBirthYear = DateTime.Now.Year;
								Tools.SilentLogit("Min > Now:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
								individual.DidEstimate = true;
							}
							if ( individual.MaxBirthYear > DateTime.Now.Year ) 
							{
								individual.MaxBirthYear = DateTime.Now.Year;
								Tools.SilentLogit("Max > Now:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
								individual.DidEstimate = true;
							}
							if ( individual.MinBirthYear == individual.MaxBirthYear ) 
							{
								individual.BirthDateText = individual.MinBirthYear.ToString() + " (calc)";
								Tools.SilentLogit("Min = Max:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
								individual.DidEstimate = true;
							} 
							else 
							{
								individual.BirthDateText = "between " + individual.MinBirthYear.ToString() + " and " + individual.MaxBirthYear.ToString() + " (calc)";
								Tools.SilentLogit("Did Estimate:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
								individual.DidEstimate = true;
							}
						}
					}
					if ( individual.MinBirthYear < MIN_ALLOWED_YEAR ) 
					{
						individual.MinBirthYear = MIN_ALLOWED_YEAR;
						Tools.SilentLogit("Min < MIN_ALLOWED_YEAR:" + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
						individual.DidEstimate = true;
					}
					if ( individual.MaxBirthYear < 0 ) 
					{
						individual.MaxBirthYear = MIN_ALLOWED_YEAR;
						Tools.SilentLogit("Max < MIN_ALLOWED_YEAR " + individual.MinBirthYear.ToString() + ":" + individual.MaxBirthYear + " " + individual.ID + ":" + individual.Forenames + " " + individual.Surname);
						individual.DidEstimate = true;
					}

				} //
				Console.Write(".");
			} //
			Console.WriteLine("");

		}

		/// <summary>
		/// Summary of ExcludeLivingIndividuals.
		/// </summary>
		/// 		
		public void ExcludeLivingIndividuals() 
		{
			// Individual theIndividual;
			DateTime dtActualDate = new DateTime();
			int iYear = 0;
			bool bIsAbout = false;
			int iEstimateStyle = 0;
			string  sFamKey;
			int jCnt;
			int iCnt;
			Tools ugt = new Tools();
			int birthCutOff;

			birthCutOff = DateTime.Now.Year - configSettings.BirthCutOffYears;

			Tools.Logit("Excluding living individuals born after " + birthCutOff.ToString() + "....");
			for ( iCnt = MyIndividuals.Count - 1 ; iCnt <= 0; iCnt--)
			{
				if ( MyIndividuals[iCnt].BirthDateText.Length != 0 ) 
				{

					Tools.GetDates(MyIndividuals[iCnt].BirthDateText, ref dtActualDate, ref iYear, ref bIsAbout, ref iEstimateStyle);

					//if they were born after the cutoff and they are still living 
					//or their birth = 0 and we are doing date estimation....
					if ((iYear >= birthCutOff && MyIndividuals[iCnt].DeathDateText.Length == 0) || (iYear == 0 && configSettings.DoDateEstimation == true) ) 
					{
						if ( MyIndividuals[iCnt].FamList.Count > 0 ) 
						{
							for ( jCnt = 1 ; jCnt <= MyIndividuals[iCnt].FamList.Count; jCnt++)
							{
								if ( MyIndividuals[iCnt].Sex == "F" ) 
								{
									MyFamilies[MyIndividuals[iCnt].FamList[jCnt].FamId].Wife = "?";
								} 
								else 
								{
									MyFamilies[MyIndividuals[iCnt].FamList[jCnt].FamId].Husband = "?";
								}
							} //
						}
						sFamKey = MyIndividuals[iCnt].FamilyID + MyIndividuals[iCnt].ID;
						try 
						{
							MyChildren.Remove(sFamKey);
						} 
						catch
						{
							//empty catch
						}
						try 
						{
							MyIndividuals.Remove(iCnt);
						} 
						catch 
						{
							//empty catch
						}
					}
				}

			} //

			//now eliminate families where both parents are unknown
			for ( iCnt = MyFamilies.Count - 1 ; iCnt <= 0;  iCnt--)
			{
				if ( MyFamilies[iCnt].Wife == "?" && MyFamilies[iCnt].Husband == "?" ) 
				{
					MyFamilies.Remove(iCnt);
				}
			} //

		}

		/// <summary>
		/// Summary of SaveEstimatedDatesList.
		/// </summary>
		/// 		
		public void SaveEstimatedDatesList() 
		{
			FileStream fs1;
			StreamWriter sw1;
			string  sFile;
			string  estDateString;
			string  tmgDateString;
			int numInList = 0;
			
			sFile = Tools.GetPath() + "\\EstimatedDates.txt";
			fs1 = new FileStream(sFile, FileMode.Create);
			sw1 = new StreamWriter(fs1);

			foreach (Individual theIndividual in MyIndividuals)
			{
				if ( theIndividual.DidEstimate == true ) 
				{
					if ( theIndividual.MinBirthYear != 0 ) 
					{
						if ( theIndividual.MinBirthYear == theIndividual.MaxBirthYear ) 
						{
							estDateString = "EST " + theIndividual.MinBirthYear.ToString();
							tmgDateString = "1" + theIndividual.MinBirthYear.ToString() + "0000010000000000";
						} 
						else 
						{
							estDateString = "BET " + theIndividual.MinBirthYear.ToString() + " AND " + theIndividual.MaxBirthYear.ToString();
							tmgDateString = "1" + theIndividual.MinBirthYear.ToString() + "000005" + theIndividual.MaxBirthYear.ToString() + "000000";
						}
						sw1.WriteLine(theIndividual.ID + "," + theIndividual.Forenames + " /" + theIndividual.Surname + "/," + estDateString + "," + FixRin(theIndividual.ID));

						numInList += 1;
					}
				}
			} //

			sw1.WriteLine(string .Format("List Total: {0}", numInList));

			sw1.Close();
			fs1.Close();
		}

		/// <summary>
		/// Summary of SetMinYear.
		/// </summary>
		/// <param name=oldMinYear></param>
		/// <param name=newMinYear></param>
		/// 		
		private int SetMinYear( int oldMinYear,  int newMinYear) 
		{
			if ( newMinYear < oldMinYear ) 
			{
				return oldMinYear;
			} 
			else 
			{
				return newMinYear;
			}
		}

		/// <summary>
		/// Summary of SetMaxYear.
		/// </summary>
		/// <param name=oldMaxYear></param>
		/// <param name=newMaxYear></param>
		/// 		
		private int SetMaxYear( int oldMaxYear,  int newMaxYear) 
		{
			if ( newMaxYear > oldMaxYear ) 
			{
				return oldMaxYear;
			} 
			else 
			{
				return newMaxYear;
			}
		}


		#endregion
			
	}

}
